diff options
| author | Richard Kistruck | 2008-12-16 17:46:45 +0000 |
|---|---|---|
| committer | Richard Kistruck | 2008-12-16 17:46:45 +0000 |
| commit | cbe281b73c1dbaac456237d96f2396e8323d04c2 (patch) | |
| tree | f4c3a350825b8484159b1e0beea8f06e35f62e40 /mps/code | |
| parent | cd8f0ed2ad9c3580594d260a7e7aa64d11fa47cf (diff) | |
| download | emacs-cbe281b73c1dbaac456237d96f2396e8323d04c2.tar.gz emacs-cbe281b73c1dbaac456237d96f2396e8323d04c2.zip | |
Mps br/timing z001989a.c: "!" means get but don't discarrd messages,
to check MPS copes okay. See .discard.
Also: improve comments.
Copied from Perforce
Change: 166953
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/z001989a.c | 106 |
1 files changed, 83 insertions, 23 deletions
diff --git a/mps/code/z001989a.c b/mps/code/z001989a.c index 1e26c563eb0..3c5c82f1473 100644 --- a/mps/code/z001989a.c +++ b/mps/code/z001989a.c | |||
| @@ -30,20 +30,24 @@ | |||
| 30 | * The actions, messages to check for, and get times, are scripted | 30 | * The actions, messages to check for, and get times, are scripted |
| 31 | * using a simple text code: | 31 | * using a simple text code: |
| 32 | * C - action: request garbage-collection; | 32 | * C - action: request garbage-collection; |
| 33 | * F - action: make a (registered)finalized object unreachable; | 33 | * F - action: make a (registered)finalized object unreachable |
| 34 | * (note: this drops the myroot ref, but some objects are | ||
| 35 | * deliberately kept alive by additional references; see | ||
| 36 | * .keep-alive) | ||
| 34 | * b - message produced: collection begin (mps_message_type_gc_start); | 37 | * b - message produced: collection begin (mps_message_type_gc_start); |
| 35 | * e - message produced: collection end (mps_message_type_gc); | 38 | * e - message produced: collection end (mps_message_type_gc); |
| 36 | * f - message produced: finalization (mps_message_type_finalization); | 39 | * f - message produced: finalization (mps_message_type_finalization); |
| 37 | * . - get messages. | 40 | * . - get messages. |
| 41 | * ! - get messages without discarding (see .discard). | ||
| 38 | * | 42 | * |
| 39 | * Example: | 43 | * Example: |
| 40 | * script "Cbe.FFCbffe.Cbe" | 44 | * script "Cbe.FFCbffe.Cbe" |
| 41 | * means: | 45 | * means: |
| 42 | * Requests a collection and checks for _gc_start and _gc messages | 46 | * Request a collection and check for _gc_start and _gc messages |
| 43 | * (in that order, and no other messages). Then drops refs to two | 47 | * (in that order, and no other messages). Then drop refs to two |
| 44 | * objects, requests another collection, and checks for _gc_start, | 48 | * objects, request another collection, and check for _gc_start, |
| 45 | * the two finalization messages (in either order), and _gc. Then | 49 | * the two finalization messages (in either order), and _gc. Then |
| 46 | * Requests a third collection and ends the test WITHOUT GETTING | 50 | * request a third collection and end the test WITHOUT GETTING |
| 47 | * the last two messages (note: no "."), to test that | 51 | * the last two messages (note: no "."), to test that |
| 48 | * mps_arena_destroy copes with ungot messages. | 52 | * mps_arena_destroy copes with ungot messages. |
| 49 | * | 53 | * |
| @@ -118,8 +122,17 @@ enum { | |||
| 118 | * Get messages, report what was got, check they are the expected | 122 | * Get messages, report what was got, check they are the expected |
| 119 | * messages, and (for finalization messages) check that these objects | 123 | * messages, and (for finalization messages) check that these objects |
| 120 | * should have been finalized (because we made them unreachable). | 124 | * should have been finalized (because we made them unreachable). |
| 125 | * | ||
| 126 | * .discard: The client should always call mps_message_discard when | ||
| 127 | * it has finished with the message. But calling with the "discard" | ||
| 128 | * parameter set to false lets us check how the MPS handles naughty | ||
| 129 | * clients. The undiscarded messages should be cleared up by | ||
| 130 | * ArenaDestroy. In a diagnostic variety (eg .variety.di) the | ||
| 131 | * ArenaDestroy diag shows the contents of the control pool, and you | ||
| 132 | * can clearly see the undiscarded messages (just before the control | ||
| 133 | * pool is destroyed). | ||
| 121 | */ | 134 | */ |
| 122 | static void report(mps_arena_t arena, const char *pm) | 135 | static void report(mps_arena_t arena, const char *pm, Bool discard) |
| 123 | { | 136 | { |
| 124 | int found = 0; | 137 | int found = 0; |
| 125 | char mFound = '\0'; | 138 | char mFound = '\0'; |
| @@ -139,13 +152,11 @@ static void report(mps_arena_t arena, const char *pm) | |||
| 139 | switch(type) { | 152 | switch(type) { |
| 140 | case mps_message_type_gc_start(): { | 153 | case mps_message_type_gc_start(): { |
| 141 | printf(" Begin Collection\n"); | 154 | printf(" Begin Collection\n"); |
| 142 | mps_message_discard(arena, message); | ||
| 143 | mFound = 'b'; | 155 | mFound = 'b'; |
| 144 | break; | 156 | break; |
| 145 | } | 157 | } |
| 146 | case mps_message_type_gc(): { | 158 | case mps_message_type_gc(): { |
| 147 | printf(" End Collection\n"); | 159 | printf(" End Collection\n"); |
| 148 | mps_message_discard(arena, message); | ||
| 149 | mFound = 'e'; | 160 | mFound = 'e'; |
| 150 | break; | 161 | break; |
| 151 | } | 162 | } |
| @@ -157,7 +168,6 @@ static void report(mps_arena_t arena, const char *pm) | |||
| 157 | cdie(myroot[objind] == NULL, "finalized live"); | 168 | cdie(myroot[objind] == NULL, "finalized live"); |
| 158 | cdie(state[objind] == finalizableSTATE, "not finalizable"); | 169 | cdie(state[objind] == finalizableSTATE, "not finalizable"); |
| 159 | state[objind] = finalizedSTATE; | 170 | state[objind] = finalizedSTATE; |
| 160 | mps_message_discard(arena, message); | ||
| 161 | mFound = 'f'; | 171 | mFound = 'f'; |
| 162 | break; | 172 | break; |
| 163 | } | 173 | } |
| @@ -167,6 +177,10 @@ static void report(mps_arena_t arena, const char *pm) | |||
| 167 | } | 177 | } |
| 168 | } | 178 | } |
| 169 | 179 | ||
| 180 | if(discard) { | ||
| 181 | mps_message_discard(arena, message); /* .discard */ | ||
| 182 | } | ||
| 183 | |||
| 170 | cdie('\0' != *pm, "Found message, but did not expect any"); | 184 | cdie('\0' != *pm, "Found message, but did not expect any"); |
| 171 | cdie(mFound == *pm, "Found message type != Expected message type"); | 185 | cdie(mFound == *pm, "Found message type != Expected message type"); |
| 172 | pm++; | 186 | pm++; |
| @@ -187,7 +201,7 @@ static void testscriptC(mps_arena_t arena, const char *script) | |||
| 187 | unsigned hiNext = myrootCOUNT - 1; | 201 | unsigned hiNext = myrootCOUNT - 1; |
| 188 | unsigned i; | 202 | unsigned i; |
| 189 | const char *scriptAll = script; | 203 | const char *scriptAll = script; |
| 190 | char am[10]; /* Array of Messages (expected but not yet got) */ | 204 | char am[100]; /* Array of Messages (expected but not yet got) */ |
| 191 | char *pmNext = am; /* Pointer to where Next Message will be stored */ | 205 | char *pmNext = am; /* Pointer to where Next Message will be stored */ |
| 192 | 206 | ||
| 193 | while(*script != '\0') { | 207 | while(*script != '\0') { |
| @@ -195,11 +209,22 @@ static void testscriptC(mps_arena_t arena, const char *script) | |||
| 195 | case '.': { | 209 | case '.': { |
| 196 | *pmNext = '\0'; | 210 | *pmNext = '\0'; |
| 197 | printf(" Getting messages (expecting \"%s\")...\n", am); | 211 | printf(" Getting messages (expecting \"%s\")...\n", am); |
| 198 | report(arena, am); | 212 | report(arena, am, TRUE); |
| 199 | printf(" ...done.\n"); | 213 | printf(" ...done.\n"); |
| 200 | pmNext = am; | 214 | pmNext = am; |
| 201 | break; | 215 | break; |
| 202 | } | 216 | } |
| 217 | case '!': { | ||
| 218 | *pmNext = '\0'; | ||
| 219 | printf(" Getting messages (expecting \"%s\")...\n", am); | ||
| 220 | /* FALSE: see .discard */ | ||
| 221 | report(arena, am, FALSE); | ||
| 222 | printf(" ...done.\n"); | ||
| 223 | printf(" NOTE: DELIBERATELY FAILING TO DISCARD MESSAGES, " | ||
| 224 | "TO SEE HOW MPS COPES.\n"); /* .discard */ | ||
| 225 | pmNext = am; | ||
| 226 | break; | ||
| 227 | } | ||
| 203 | case 'C': { | 228 | case 'C': { |
| 204 | printf(" Collect\n"); | 229 | printf(" Collect\n"); |
| 205 | mps_arena_collect(arena); | 230 | mps_arena_collect(arena); |
| @@ -210,8 +235,10 @@ static void testscriptC(mps_arena_t arena, const char *script) | |||
| 210 | i = isLoNext ? loNext++ : hiNext--; | 235 | i = isLoNext ? loNext++ : hiNext--; |
| 211 | isLoNext = 1 - isLoNext; | 236 | isLoNext = 1 - isLoNext; |
| 212 | 237 | ||
| 213 | printf(" drop ref to make object %u Finalizable\n", i); | 238 | printf(" Drop myroot ref to object %u -- " |
| 214 | /* make i finalizable */ | 239 | "this might make it Finalizable\n", i); |
| 240 | /* drop myroot ref, to perhaps make i finalizable */ | ||
| 241 | /* (but see .keep-alive) */ | ||
| 215 | myroot[i] = NULL; | 242 | myroot[i] = NULL; |
| 216 | state[i] = finalizableSTATE; | 243 | state[i] = finalizableSTATE; |
| 217 | break; | 244 | break; |
| @@ -302,17 +329,30 @@ static void *testscriptB(void *arg, size_t s) | |||
| 302 | state[i] = rootSTATE; | 329 | state[i] = rootSTATE; |
| 303 | } | 330 | } |
| 304 | 331 | ||
| 305 | /* leave 0 and N containing NULL refs */ | 332 | /* .keep-alive: Create some additional inter-object references. |
| 333 | * | ||
| 334 | * 1 and N-1 don't die until myroot refs to both have been nulled. | ||
| 335 | * | ||
| 336 | * 2 and 3 don't die until myroot refs to both have been nulled. | ||
| 337 | * | ||
| 338 | * We do this to check that reachability via non-root refs prevents | ||
| 339 | * finalization. | ||
| 340 | */ | ||
| 341 | |||
| 342 | /* Leave 0 and N containing NULL refs */ | ||
| 306 | 343 | ||
| 307 | /* make 1 and N-1 refer to each other */ | 344 | /* Make 1 and N-1 refer to each other */ |
| 308 | DYLAN_VECTOR_SLOT(myroot[1] , 1) = (mps_word_t)myroot[N-1]; | 345 | DYLAN_VECTOR_SLOT(myroot[1] , 1) = (mps_word_t)myroot[N-1]; |
| 309 | DYLAN_VECTOR_SLOT(myroot[N-1], 1) = (mps_word_t)myroot[1]; | 346 | DYLAN_VECTOR_SLOT(myroot[N-1], 1) = (mps_word_t)myroot[1]; |
| 310 | 347 | ||
| 311 | /* make 2 and 3 refer to each other */ | 348 | /* Make 2 and 3 refer to each other */ |
| 312 | DYLAN_VECTOR_SLOT(myroot[2], 1) = (mps_word_t)myroot[3]; | 349 | DYLAN_VECTOR_SLOT(myroot[2], 1) = (mps_word_t)myroot[3]; |
| 313 | DYLAN_VECTOR_SLOT(myroot[3], 1) = (mps_word_t)myroot[2]; | 350 | DYLAN_VECTOR_SLOT(myroot[3], 1) = (mps_word_t)myroot[2]; |
| 314 | 351 | ||
| 315 | /* stop stack scanning, to prevent unwanted object retention */ | 352 | /* Stop stack scanning, otherwise stack or register dross from */ |
| 353 | /* these setup functions can cause unwanted object retention, */ | ||
| 354 | /* which would mean we don't get the finalization messages we */ | ||
| 355 | /* expect. */ | ||
| 316 | mps_root_destroy(root_stackreg); | 356 | mps_root_destroy(root_stackreg); |
| 317 | 357 | ||
| 318 | mps_message_type_enable(arena, mps_message_type_gc_start()); | 358 | mps_message_type_enable(arena, mps_message_type_gc_start()); |
| @@ -374,18 +414,38 @@ int main(int argc, char **argv) | |||
| 374 | 414 | ||
| 375 | randomize(argc, argv); | 415 | randomize(argc, argv); |
| 376 | 416 | ||
| 377 | /* really basic scripts */ | 417 | /* Scripts that should fail (uncomment to show failure is detected) */ |
| 418 | /*testscriptA("C.");*/ | ||
| 419 | /*testscriptA("b.");*/ | ||
| 420 | |||
| 421 | /* The most basic scripts */ | ||
| 422 | testscriptA("."); | ||
| 378 | testscriptA("Cbe."); | 423 | testscriptA("Cbe."); |
| 424 | testscriptA("Cbe.Cbe."); | ||
| 425 | |||
| 426 | /* Get messages, but not promptly */ | ||
| 379 | testscriptA(".Cbe.CbeCbeCbe."); | 427 | testscriptA(".Cbe.CbeCbeCbe."); |
| 380 | testscriptA(".Cbe.CbeCbeCbe"); | ||
| 381 | 428 | ||
| 382 | /* simple finalization */ | 429 | /* Ungot messages at ArenaDestroy */ |
| 430 | testscriptA("Cbe"); | ||
| 431 | testscriptA("Cbe.CbeCbeCbe"); | ||
| 432 | |||
| 433 | /* Fail to call mps_message_discard */ | ||
| 434 | testscriptA("Cbe!"); | ||
| 435 | testscriptA("Cbe!CbeCbeCbe!"); | ||
| 436 | |||
| 437 | /* Simple finalization | ||
| 438 | * | ||
| 439 | * These tests rely on the particular order in which the "F" command | ||
| 440 | * nulls-out references. Not every "F" makes an object finalizable. | ||
| 441 | * See .keep-alive. | ||
| 442 | */ | ||
| 383 | testscriptA("FFCbffe."); | 443 | testscriptA("FFCbffe."); |
| 384 | testscriptA("FFCbffe.FFCbffe."); | 444 | testscriptA("FFCbffe.FFCbffe."); |
| 385 | testscriptA("FFCbffe.FCbe.F.Cbffe.FFCbfe.FF.Cbfffe."); | 445 | testscriptA("FFCbffe.FCbe.F.Cbffe.FFCbfe.FF.Cbfffe."); |
| 386 | 446 | ||
| 387 | /* test failure: */ | 447 | /* Various other scripts */ |
| 388 | /*testscriptA("FC.");*/ | 448 | testscriptA("Cbe.FFCbffe.Cbe"); |
| 389 | 449 | ||
| 390 | fflush(stdout); /* synchronize */ | 450 | fflush(stdout); /* synchronize */ |
| 391 | fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); | 451 | fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); |