/* 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 must be cleared up by * ArenaDestroy. */ 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 %"PRIuLONGEST" at %p\n", (ulongest_t)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"); }
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"); switch(type) { /* @@@@ is using these macros in a switch supported? */ case 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)); break; } case 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"); } break; } default: { cdie(0, "unknown message type"); break; } } mps_message_discard(arena, message); } return; }
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. * * GDR 2013-03-12: Fiddling with the commit limit was causing * the test to fail sometimes (see job003440), so I've commented * out this feature. */ /* die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit"); */ } } else { cdie(0, "unknown message type"); break; } mps_message_discard(arena, message); } return; }
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"); switch(type) { /* @@@@ is using these macros in a switch supported? */ case mps_message_type_gc_start(): printf("\nCollection start %d. Because:\n", ++nStart); printf("%s\n", mps_message_gc_start_why(arena, message)); break; case 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); } break; default: cdie(0, "unknown message type"); } mps_message_discard(arena, message); } return; }
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"); } else { cdie(0, "unknown message type"); break; } mps_message_discard(arena, message); } }
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; }
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; size_t 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; }