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(), 0x1000, 1024, 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); }
static void test(void *stack_pointer) { mps_thr_t thread; mps_pool_t pool; unsigned int i; unsigned long nLarge; cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*50)), "create arena"); cdie(mps_thread_reg(&thread, arena), "register thread"); mps_arena_commit_limit_set(arena, COMLIMIT1); die(mps_pool_create(&pool, arena, mps_class_mvff(), (size_t)EXTENDBY, (size_t)8, (mps_align_t)MPS_PF_ALIGN, (mps_bool_t)0, (mps_bool_t)0, (mps_bool_t)1), "create MVFF pool"); for (i = 0; i < NSMALL; i++) { die(mps_alloc(&smallObjects[i], pool, SMALLSIZE), "small alloc failed"); } nLarge = 0; while (mps_alloc(&largeObjects[nLarge], pool, BIGSIZE) == MPS_RES_OK) { nLarge ++; } report("nLarge", "%lu", nLarge); for (i = 0; i < NSMALL; i += 2) { mps_free(pool, smallObjects[i], SMALLSIZE); } comment("Freed every other small object."); /* The CBS should be in emergency mode now. */ for (i = 0; i < nLarge; i += 2) { mps_free(pool, largeObjects[i], BIGSIZE); } comment("Freed every other large object."); /* Now there should be lots of big blocks on the CBS. */ mps_arena_commit_limit_set(arena, COMLIMIT2); comment("Raised the commit limit. Will attempt free and alloc."); mps_free(pool, largeObjects[1], BIGSIZE); die(mps_alloc(&largeObjects[0], pool, BIGSIZE), "alloc failed"); mps_pool_destroy(pool); mps_thread_dereg(thread); mps_arena_destroy(arena); }
static void test(void) { int i; mps_addr_t a; /* create an arena with chunk size of 2 M */ cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*20)), "create arena"); cdie(mps_thread_reg(&thread, arena), "register thread"); /* set the commit limit to 10MB */ report_res("commit0", mps_arena_commit_limit_set(arena, (size_t) (1024*1024*10))); /* create a pool */ cdie(mps_pool_create(&pool, arena, mps_class_mv(), (size_t) 64, (size_t) 64, (size_t) 64), "pool create"); for (i=0; i<200; i++) { report("count", "%i", i); die(mps_alloc(&a, pool, (size_t) 1024*1024), "alloc"); } mps_pool_destroy(pool); mps_thread_dereg(thread); mps_arena_destroy(arena); comment("Destroyed arena."); }
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 %lu\n", (unsigned long)live); printf("condemned %lu\n", (unsigned long)condemned); printf("not_condemned %lu\n", (unsigned long)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"); } }
static void test(void) { int i = 0; mps_ap_t sap; mps_arena_t arena; mps_fmt_t format; mps_pool_t spool; mps_thr_t thread; mps_frame_t frame; mycell *p; /* create an arena that can't grow beyond 30 M */ cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t)THIRTY_MEG), "create arena"); cdie(mps_arena_commit_limit_set(arena, (size_t)THIRTY_MEG), "commit limit set"); cdie(mps_thread_reg(&thread, arena), "register thread"); cdie( mps_fmt_create_A(&format, arena, &fmtA), "create format"); cdie( mps_pool_create(&spool, arena, mps_class_snc(), format), "create SNC pool"); cdie( mps_ap_create(&sap, spool, mps_rank_exact()), "create ap"); /* repeatedly push, alloc 1MB object, and pop to first stack frame. This shouldn't use much more than 1MB of memory. */ for (i=0; i < ITERATIONS; i++) { die(mps_ap_frame_push(&frame, sap), "push"); p = allocdumb(sap, OBJSIZE, mps_rank_exact()); die(mps_ap_frame_pop(sap, frame), "pop"); comment("%i of %i", i, ITERATIONS); } mps_ap_destroy(sap); comment("Destroyed ap."); mps_pool_destroy(spool); comment("Destroyed pool."); mps_fmt_destroy(format); comment("Destroyed format."); mps_thread_dereg(thread); comment("Deregistered thread."); mps_arena_destroy(arena); comment("Destroyed arena."); }
static void test(void *stack_pointer) { int j; mps_ap_t ap; mps_arena_t arena; mps_fmt_t format; mps_chain_t chain; mps_pool_t pool; mps_root_t root1; mps_thr_t thread; /* create an arena that can't grow beyond 30 MB */ cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t)THIRTY_MEG), "create arena"); cdie(mps_arena_commit_limit_set(arena, (size_t)THIRTY_MEG), "commit limit set"); cdie(mps_thread_reg(&thread, arena), "register thread"); cdie(mps_root_create_table(&root1, arena, mps_rank_exact(), 0, (mps_addr_t*)&exfmt_root, 1), "create table root"); cdie(mps_fmt_create_A(&format, arena, &fmtA), "create format"); cdie(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); die(mmqa_pool_create_chain(&pool, arena, mps_class_amc(), format, chain), "create pool"); cdie(mps_ap_create(&ap, pool, mps_rank_exact()), "create ap"); /* allocate a 16 MB live object */ allocdumb(ap, 16*MEG, mps_rank_exact()); comment("collect world..."); for (j=0; j<1000; j++) { mps_arena_collect(arena); } mps_arena_park(arena); mps_ap_destroy(ap); mps_pool_destroy(pool); mps_chain_destroy(chain); mps_fmt_destroy(format); mps_root_destroy(root1); mps_thread_dereg(thread); mps_arena_destroy(arena); comment("Destroyed arena."); }
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; }
/** Shared release method of the commit extension low-memory handlers. */ static Bool mm_commit_release(low_mem_handler_t *handler, corecontext_t *context, low_mem_offer_t *offer) { mm_commit_extension_t *extension = (mm_commit_extension_t *)handler; size_t limit; mps_res_t res; HQASSERT(handler != NULL, "No handler"); HQASSERT(context != NULL, "No context"); HQASSERT(offer != NULL, "No offer"); HQASSERT(offer->next == NULL, "Multiple offers"); UNUSED_PARAM(corecontext_t*, context); #ifdef REGAIN_AT_FREE if ( !multi_mutex_trylock(&reserve_mutex) ) return TRUE; /* give up if can't get the lock */ /* Other threads might have reduced the commit limit since the offer, but this thread still needs the same amount memory as before. */ #endif HQASSERT(mm_commit_limit == mps_arena_commit_limit(mm_arena), "mm_commit_limit out of synch with MPS"); HQASSERT(mm_commit_limit < extension->limit, "Commit limit raised unexpectedly."); limit = min(mm_commit_limit + max(offer->taken_size, extension->delta), extension->limit); res = mps_arena_commit_limit_set(mm_arena, limit); HQASSERT(res == MPS_RES_OK, "Failed to set commit limit"); mm_commit_limit = limit; mm_memory_is_low = TRUE; MM_LOG(( LOG_CX, "0x%08x", mm_commit_limit )); #if defined( DEBUG_BUILD ) { /* If extending without limit, warn the user. */ mm_commit_extension_t *extension = limit <= mm_arena_extension.limit ? &mm_arena_extension : &mm_use_all; if ( !extension->reported ) { if ( extension != &mm_arena_extension ) monitorf((uint8 *)"Warning: using all available memory\n"); extension->reported = TRUE; } } #endif #ifdef REGAIN_AT_FREE multi_mutex_unlock(&reserve_mutex); #endif return TRUE; }
static void runArenaTest(size_t size, mps_bool_t failcase, mps_bool_t usefulFailcase) { mps_arena_t arena; die(mps_arena_create(&arena, mps_arena_class_vmnz(), size), "mps_arena_create"); die(mps_arena_commit_limit_set(arena, size - chunkSize), "mps_arena_commit_limit_set"); testInArena(arena, failcase, usefulFailcase); mps_arena_destroy(arena); }
/** \brief Reduce the commit limit as far as possible within the extension, but only down to the cost given. Callers must shrink in the right order, so this will not be called when the commit limit is above the range of this extension, unless the cost limit is above it as well (this simplifies the callers). */ static Bool mm_shrink(mm_commit_extension_t *extension, mm_cost_t cost_limit) { size_t curr_limit; Bool enough = TRUE; curr_limit = mm_commit_limit; HQASSERT(curr_limit == mps_arena_commit_limit( mm_arena ), "mm_commit_limit out of synch with MPS"); HQASSERT(mm_commit_limit >= mm_arena_extension.base && mm_commit_limit <= mm_use_all.limit, "mm_commit_limit out of range"); if ( !mm_cost_less_than(cost_limit, extension->cost) ) return TRUE; HQASSERT(curr_limit <= extension->limit, "Shrinking using the wrong extension."); while ( curr_limit > extension->base ) { size_t trylimit; /* Now reduce the current limit, capping at the base for this level */ trylimit = curr_limit - extension->delta; if ( trylimit > curr_limit /* wrap around */ || trylimit < extension->base ) trylimit = extension->base; /* Try to set the new limit */ if ( mps_arena_commit_limit_set( mm_arena, trylimit ) != MPS_RES_OK ) { enough = FALSE; break; /* still holding too much memory! */ } curr_limit = trylimit; } if ( curr_limit != mm_commit_limit ) { mm_commit_limit = curr_limit; MM_LOG(( LOG_CS, "0x%08x", mm_commit_limit )); HQASSERT(mm_reserve_level == 0, "Shouldn't get here while using the reserve pool."); if ( mm_commit_limit == mm_commit_base ) mm_memory_is_low = FALSE; } return enough; }
static void test(void) { mps_arena_t arena; mps_pool_t pool; mps_addr_t q; int p; die(mps_arena_create(&arena, mps_arena_class_vmnz(), VMNZSIZE), "create"); die(mps_arena_commit_limit_set(arena, VMNZSIZE), "commit limit"); die(mps_pool_create(&pool, arena, mps_class_mv(), EXTENDBY, AVGSIZE, EXTENDBY), "pool create"); for (p=0; p<ITERATE; p++) { die(mps_alloc(&q, pool, PROMISE*1024), "alloc"); q = (mps_addr_t) ((char *) q + 8); mps_free(pool, q, PROMISE*1024-8); report("promise", "%i", p); } mps_pool_destroy(pool); mps_arena_destroy(arena); }
static void t_alloc(int spare, int spare_total, int commit, int obj_size) { size_t size, hisize, comsize, comlimit; size_t spsize = 0, losize = 0; /* stop warnings */ mps_res_t res, res_expected; if (obj_size == OBJ_SMALL) size = SMALL_SIZE; else size = BIG_SIZE; switch (spare_total) { case SPARE_EMPTY: spsize = 0; break; case SPARE_LESS: if (size > DIFF_SIZE) { spsize = size-DIFF_SIZE; } else { spsize = 0; } break; case SPARE_EXACT: spsize = size; break; case SPARE_MORE: spsize = size+DIFF_SIZE; break; default: error("Illegal spare.\n"); break; } switch (spare) { case SPARE_EMPTY: losize = 0; break; case SPARE_LESS: if (size > DIFF_SIZE) { losize = size-DIFF_SIZE; } else { losize = 0; } break; case SPARE_EXACT: losize = size; break; case SPARE_MORE: losize = size+DIFF_SIZE; break; } if (losize > spsize) { losize = spsize; hisize = 0; } else { hisize = spsize-losize; } /* turn off commit limit for a moment */ mps_arena_commit_limit_set(arena, HUGE); /* create low and high pools */ die( mps_pool_create(&poolhi, arena, mps_class_mvff(), MVFF_HI_PARMS), "create high pool"); die( mps_pool_create(&poollo, arena, mps_class_mvff(), MVFF_LO_PARMS), "create low pool"); /* flush hysteresis fund, then set limit */ mps_arena_spare_commit_limit_set(arena, SPARE_ZERO); mps_arena_spare_commit_limit_set(arena, SPARE_LIMIT); /* allocate something in each pool (to reduce risk of subsidiary allocation being neede later */ die(mps_alloc(&objlo, poollo, EXTEND), "low alloc"); die(mps_alloc(&objhi, poolhi, EXTEND), "high alloc"); /* set up spare committed the way we want it */ if (losize>0) { die(mps_alloc(&objlo, poollo, losize), "low setup"); mps_free(poollo, objlo, losize); } if (hisize>0) { die(mps_alloc(&objhi, poolhi, hisize), "high setup"); mps_free(poolhi, objhi, hisize); } /* spare is now set up correctly */ /* now we need to set the commit limit correctly */ comsize = arena_committed_and_used(arena); /* allow for 1/16th memory overhead in setting commit limit */ if (commit == COMMIT_EXACT) { comlimit = comsize+size+(size/16); } else if (commit == COMMIT_NOCHANGE) { comlimit = mps_arena_committed(arena); } else if (commit == COMMIT_PLENTY) { comlimit = HUGE; } else /* commit == COMMIT_LITTLE */ { if (size > DIFF_SIZE) { comlimit = comsize+size+(size/16)+DIFF_SIZE; } else { comlimit = comsize+size+(size/16); } } die(mps_arena_commit_limit_set(arena, comlimit), "commit limit set"); res = mps_alloc(&objlo, poollo, size); asserts(comlimit >= comsize, "comlimit was less than comsize!"); if (size <= (comlimit-comsize)) { res_expected = MPS_RES_OK; } else { res_expected = MPS_RES_COMMIT_LIMIT; } if (res != res_expected) { comment("Spare useful/total %i/%i. Limit %i. Size %i. Expected %s. Got %s", spare, spare_total, commit, obj_size, err_text(res_expected), err_text(res)); report("failed", "yes"); } mps_pool_destroy(poollo); mps_pool_destroy(poolhi); }
static void test(void) { mycell *p, *q; int i; mps_res_t res; size_t lim0, avail0, lim1, avail1, commit1, lim2, avail2, commit2; size_t lim3, avail3, commit3, lim4, avail4, commit4; size_t lim5, avail5, commit5, lim6, avail6, commit6; cdie(mps_arena_create(&arena, mps_arena_class_vm(), ARENA_SIZE), "create arena"); cdie(mps_thread_reg(&thread, arena), "register thread"); cdie(mps_root_create_reg(&root, arena, mps_rank_ambig(), 0, thread, mps_stack_scan_ambig, stackpointer, 0), "create stack root"); cdie( mps_fmt_create_A(&format, arena, &fmtA), "create format"); cdie( mps_pool_create(&poolsnc, arena, mps_class_snc(), format), "create pool"); cdie( mps_ap_create(&apsnc, poolsnc, mps_rank_exact()), "create ap"); report("lim0", "%d", lim0 = mps_reservoir_limit(arena)); report("avail0", "%d", avail0 = mps_reservoir_available(arena)); mps_reservoir_limit_set(arena, (size_t) 0); mps_reservoir_limit_set(arena, (size_t) (5ul*1024*1024)); report("lim1", "%d", lim1 = mps_reservoir_limit(arena)); report("avail1", "%d", avail1 = mps_reservoir_available(arena)); report("commit1", "%d", commit1 = arena_committed_and_used(arena)); report("defecit1", "%d", lim1-avail1); mps_reservoir_limit_set(arena, (size_t) (1045)); report("lim2", "%d", lim2 = mps_reservoir_limit(arena)); report("avail2", "%d", avail2 = mps_reservoir_available(arena)); report("commit2", "%d", commit2 = arena_committed_and_used(arena)); report("defecit2", "%d", lim2-avail2); /* set commit limit to whatever is currently committed plus 1 MB */ die(mps_arena_commit_limit_set(arena, arena_committed_and_used(arena)+1024*1024), "commit limit set"); mps_reservoir_limit_set(arena, (size_t) (10ul*1024*1024)); report("lim3", "%d", lim3 = mps_reservoir_limit(arena)); report("avail3", "%d", avail3 = mps_reservoir_available(arena)); report("commit3", "%d", commit3 = arena_committed_and_used(arena)); report("defecit3", "%d", lim3-avail3); report("spill3", "%d", commit3-mps_arena_commit_limit(arena)); /* now raise it by 1/2 MB -- reservoir should grow */ die(mps_arena_commit_limit_set(arena, arena_committed_and_used(arena)+512*1024), "commit limit set"); report("lim4", "%d", lim4 = mps_reservoir_limit(arena)); report("avail4", "%d", avail4 = mps_reservoir_available(arena)); report("commit4", "%d", commit4 = arena_committed_and_used(arena)); report("grow4", "%d", avail4-avail3); report("spill4", "%d", commit4-mps_arena_commit_limit(arena)); /* try some allocation -- more than a small amount should fail */ i = -1; p = NULL; res = MPS_RES_OK; while (res == MPS_RES_OK) { res = allocrone(&q, apsnc, 10, mps_rank_exact()); if (res == MPS_RES_OK) { setref(q, 0, p); p = q; } i++; } report("allocfail", "%d", i); report_res("failres", res); /* available shouldn't have changed since before allocation */ report("lim5", "%d", lim5 = mps_reservoir_limit(arena)); report("avail5", "%d", avail5 = mps_reservoir_available(arena)); report("commit5", "%d", commit5 = arena_committed_and_used(arena)); report("grow5", "%d", avail5-avail4); report("spill5", "%d", commit5-mps_arena_commit_limit(arena)); /* try some allocation from reservoir -- not much should fail */ i = -1; res = MPS_RES_OK; while (res == MPS_RES_OK) { res = reservoir_allocrone(&q, apsnc, 10, mps_rank_exact()); if (res == MPS_RES_OK) { setref(q, 0, p); p = q; } i++; } report("allocfail2", "%d", i); report_res("failres2", res); /* available should have changed now */ report("lim6", "%d", lim6 = mps_reservoir_limit(arena)); report("avail6", "%d", avail6 = mps_reservoir_available(arena)); report("commit6", "%d", commit6 = arena_committed_and_used(arena)); report("spill6", "%d", commit6-mps_arena_commit_limit(arena)); report("shrink6", "%d", avail5-avail6); mps_root_destroy(root); comment("Destroyed root."); mps_ap_destroy(apsnc); comment("Destroyed ap."); mps_pool_destroy(poolsnc); comment("Destroyed pool."); mps_fmt_destroy(format); comment("Destroyed format."); mps_thread_dereg(thread); comment("Deregistered thread."); mps_arena_destroy(arena); comment("Destroyed arena."); }
static void test(void) { mps_pool_t pool; mps_thr_t thread; mps_root_t root, root1; mps_fmt_t format; mps_chain_t chain; mps_ap_t ap; mycell *a, *b; mps_addr_t base, *addr; mps_res_t res; int j; /* create an arena that can't grow beyond 30 M */ cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*30)), "create arena"); die(mps_arena_commit_limit_set(arena, (size_t) (1024*1024*30)), "limit"); die(mps_thread_reg(&thread, arena), "register thread"); die(mps_root_create_reg(&root, arena, mps_rank_ambig(), 0, thread, mps_stack_scan_ambig, stackpointer, 0), "create root"); base = &exfmt_root; addr = base; cdie( mps_root_create_table(&root1,arena,mps_rank_ambig(),0,addr,1), "create table root"); cdie(mps_fmt_create_A(&format, arena, &fmtA), "create format"); cdie(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); die(mmqa_pool_create_chain(&pool, arena, mps_class_amc(), format, chain), "create pool"); cdie( mps_ap_create(&ap, pool, mps_rank_exact()), "create ap"); /* allocate 16 M of (live) stuff */ b = allocone(ap, 2, mps_rank_exact()); for (j=0; j<160; j++) { a = allocone(ap, 2, mps_rank_exact()); setref(a, 0, b); b = allocdumb(ap, 1024*100, mps_rank_exact()); setref(a, 1, b); b = a; } comment("created 16M of live objects"); fillup(); comment("try to make collect by allocating another 1G..."); empty(); for (j=0; j<1000*1024; j++) { res=allocrdumb(&a, ap, 1024, mps_rank_exact()); if (res == MPS_RES_OK) { comment("%i ok", j); } else { break; } } comment("collect world..."); for (j=0; j<10; j++) { mps_arena_collect(arena); } mps_arena_park(arena); mps_ap_destroy(ap); mps_pool_destroy(pool); mps_chain_destroy(chain); mps_fmt_destroy(format); mps_root_destroy(root); mps_root_destroy(root1); mps_thread_dereg(thread); mps_arena_destroy(arena); comment("Destroyed arena."); }
static void test(void) { int i = 0, f = 0; mps_ap_t sap; mps_arena_t arena; mps_fmt_t format; mps_pool_t spool; mps_thr_t thread; mps_frame_t frames[MAXFRAMES]; int nobj[MAXFRAMES+1]; mycell *p; /* create an arena that can't grow beyond 30 M */ cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t)THIRTY_MEG), "create arena"); cdie(mps_arena_commit_limit_set(arena, (size_t)THIRTY_MEG), "commit limit set"); cdie(mps_thread_reg(&thread, arena), "register thread"); cdie( mps_fmt_create_A(&format, arena, &fmtA), "create format"); cdie( mps_pool_create(&spool, arena, mps_class_snc(), format), "create SNC pool"); cdie( mps_ap_create(&sap, spool, mps_rank_exact()), "create ap"); /* repeatedly push and pop stack frames, and allocate objects in them at random. Parameters ensure that max allocation can't get too high. */ for (i=0; i < ITERATIONS; i++) { switch (ranint(12)) { case 1: case 2: case 3: case 4: case 5: if (f < MAXFRAMES) { die(mps_ap_frame_push(&frames[f], sap), "push"); comment("push %i", f); f++; nobj[f] = 0; } break; case 6: case 7: case 8: case 9: case 10: if (nobj[f] < MAXLEVOBJS) { p = allocone(sap, 16, mps_rank_exact()); setref(p, 0, NULL); nobj[f]++; } break; case 11: if (f>0) { f -= 1+ranint(1+ranint(f)); /* new f is in [0, old f) */ die(mps_ap_frame_pop(sap, frames[f]), "pop"); comment("pop %i", f); } break; } } mps_arena_park(arena); mps_ap_destroy(sap); comment("Destroyed ap."); mps_pool_destroy(spool); comment("Destroyed pool."); mps_fmt_destroy(format); comment("Destroyed format."); mps_thread_dereg(thread); comment("Deregistered thread."); mps_arena_destroy(arena); comment("Destroyed arena."); }
static void test(void) { mps_pool_t pool; mps_thr_t thread; mps_root_t root; mps_fmt_t format; mps_chain_t chain; mps_ap_t ap, ap2; mycell *a, *b; mps_res_t res; int i; /* create an arena that can't grow beyond 30 M */ cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*40)), "create arena"); mps_arena_commit_limit_set(arena, (size_t) (1024*1024*30)); cdie(mps_thread_reg(&thread, arena), "register thread"); cdie(mps_root_create_reg(&root, arena, mps_rank_ambig(), 0, thread, mps_stack_scan_ambig, stackpointer, 0), "create root"); cdie( mps_fmt_create_A(&format, arena, &fmtA), "create format"); cdie(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); die(mmqa_pool_create_chain(&pool, arena, mps_class_amc(), format, chain), "create pool"); cdie( mps_ap_create(&ap, pool, mps_rank_exact()), "create ap"); /* allocate until full */ i = 0; b = NULL; while (allocrone(&a, ap, 128, mps_rank_exact()) == MPS_RES_OK) { i++; setref(a, 0, b); b = a; } comment("%d objs allocated.", i); report("committed", "%ld", mps_arena_committed(arena)); /* try to allocate 10 times */ cdie(mps_ap_create(&ap2, pool, mps_rank_exact()), "create second ap"); mps_ap_destroy(ap); for (i = 0; i < 10; i++) { res = allocrone(&a, ap2, 128, mps_rank_exact()); report("predie", "%s", err_text(res)); } /* now let everything die, and try to allocate 10 times */ mps_root_destroy(root); for (i = 0; i < 10; i++) { res = allocrone(&a, ap2, 128, mps_rank_exact()); report("postdie", "%s", err_text(res)); } mps_ap_destroy(ap2); mps_pool_destroy(pool); mps_chain_destroy(chain); mps_fmt_destroy(format); mps_thread_dereg(thread); mps_arena_destroy(arena); comment("Destroyed arena."); }
Bool mm_extension_init(size_t addr_space_size, size_t working_size, size_t extension_size, Bool use_all_mem) { size_t extended_commit_limit; Bool res; MM_LOG(( LOG_IP, "0x%08x 0x%08x 0x%08x 0x%08x %d", (unsigned)mm_arena, addr_space_size, working_size, extension_size, (int)use_all_mem )); if ( working_size + extension_size < working_size ) /* overflow? */ extended_commit_limit = (size_t)-1; else extended_commit_limit = working_size + extension_size; if ( addr_space_size < extended_commit_limit ) return FALSE; /* a configuration error in the skin */ mm_commit_base = working_size; /* Extension beyond working_size, into arena extension, to reduce partial * paints. */ /* Always init, so it all works when the extension is configured off. */ mm_arena_extension.base = mm_arena_extension.limit = working_size; mm_arena_extension.cost = mm_cost_none; if ( extension_size > 0 ) { mm_arena_extension.limit = extended_commit_limit; mm_arena_extension.delta = 256*1024; /* guess */ mm_arena_extension.cost.tier = memory_tier_partial_paint; mm_arena_extension.cost.value = 0.1f; HQASSERT(mm_cost_less_than(mm_arena_extension.cost, mm_cost_normal), "Default cost doesn't include arena extension."); HQASSERT(mm_cost_less_than(mm_cost_below_reserves, mm_arena_extension.cost), "mm_cost_below_reserves includes arena extension."); res = low_mem_handler_register(&mm_arena_extension.handler); if ( !res ) return FALSE; } /* Extension beyond arena extension, intended to be permitted only after * a partial paint has been attempted (or is not allowed). */ /* Always init, so it all works when the extension is configured off. */ mm_use_all.base = mm_use_all.limit = mm_arena_extension.limit; mm_use_all.cost = mm_cost_none; if ( use_all_mem ) { if ( addr_space_size > mm_arena_extension.limit ) { mm_use_all.limit = addr_space_size; mm_use_all.delta = 256*1024; /* guess */ mm_use_all.cost.tier = memory_tier_trash_vm; mm_use_all.cost.value = 1.0f; HQASSERT(mm_cost_less_than(mm_use_all.cost, mm_cost_normal), "Default cost doesn't include use-all extension."); HQASSERT(mm_cost_less_than(mm_cost_below_reserves, mm_use_all.cost), "mm_cost_below_reserves includes use-all extension."); res = low_mem_handler_register(&mm_use_all.handler); if ( !res ) return FALSE; } } /* Now set the current commit limit */ mm_commit_limit = working_size; if ( mps_arena_commit_limit_set( mm_arena, mm_commit_limit ) != MPS_RES_OK ) return FALSE; /* Try to hang onto a few a spare segments. Note that we just use a small * and fairly arbitrary number here. It's small 'cos there are few pools * which exhibit the problem of repeated allocs and frees that cause * segments to be created and destroyed (examples: dl pool, and to a much * lesser extent, color pool - as it overflows onto a second segment). */ mps_arena_spare_commit_limit_set( mm_arena, (size_t)4 * 64 * 1024 ); return TRUE; }
static void test(void) { mps_pool_t poolhi, poollo; mps_thr_t thread; unsigned long com0, com1; /* create a VM arena of 30MB */ cdie(mps_arena_create(&arena, mps_arena_class_vmnz(), (size_t) (1024*1024*40)), "create arena"); /* set the commit limit to 100MB, i.e. let the arena do the limiting */ mps_arena_commit_limit_set(arena, (size_t) (1024ul*1024ul*100ul)); cdie(mps_thread_reg(&thread, arena), "register thread"); cdie( mps_pool_create(&poolhi, arena, mps_class_mvff(), MVFF_HI_PARMS), "create high pool"); cdie( mps_pool_create(&poollo, arena, mps_class_mvff(), MVFF_LO_PARMS), "create low pool"); /* set the spare commit limit to something very big */ mps_arena_spare_commit_limit_set(arena, (size_t)-1); /* allocate a jolly big object, clamp the commit limit down, leaving 64KB space, then free it */ die(mps_alloc(&objs[0], poollo, BIGSIZE), "alloc"); com0 = mps_arena_committed(arena); mps_arena_commit_limit_set(arena, com0+(1024*64)); mps_free(poollo, objs[0], BIGSIZE); com1 = mps_arena_committed(arena); /* the free shouldn't have reduced the total amount committed */ report("reduce1", "%ld", com0-com1); /* it should be possible to reallocate the object */ die(mps_alloc(&objs[0], poollo, BIGSIZE), "alloc lo"); mps_free(poollo, objs[0], BIGSIZE); /* it should equally be possible to allocate an object in a different segment (poolhi). This ought to flush the spare. */ die(mps_alloc(&objs[0], poolhi, BIGSIZE), "alloc hi"); mps_free(poolhi, objs[0], BIGSIZE); comment("Finishing off."); mps_pool_destroy(poolhi); mps_pool_destroy(poollo); comment("Destroyed pool."); mps_thread_dereg(thread); comment("Deregistered thread."); mps_arena_destroy(arena); comment("Destroyed arena."); }
static void test(void) { mycell *p, *q; int i; mps_res_t res; size_t lim7, avail7, commit7, lim8, avail8, commit8; size_t lim9, avail9, commit9; cdie(mps_arena_create(&arena, mps_arena_class_vm(), ARENA_SIZE), "create space"); cdie(mps_thread_reg(&thread, arena), "register thread"); cdie(mps_root_create_reg(&root, arena, MPS_RANK_AMBIG, 0, thread, mps_stack_scan_ambig, stackpointer, 0), "create stack root"); cdie( mps_fmt_create_A(&format, arena, &fmtA), "create format"); cdie( mps_pool_create(&poolamc, arena, mps_class_amc(), format), "create pool"); cdie( mps_ap_create(&apamc, poolamc, MPS_RANK_EXACT), "create ap"); mps_arena_commit_limit_set(arena, mps_arena_committed(arena)+1024*1024); mps_reservoir_limit_set(arena, 0); report("lim7", "%d", lim7 = mps_reservoir_limit(arena)); report("avail7", "%d", avail7 = mps_reservoir_available(arena)); report("commit7", "%d", commit7 = mps_arena_committed(arena)); /* available should be zero, but should be able to allocate with reservoir permit, until commit_limit is reached */ i = -1; p = NULL; res = MPS_RES_OK; while (res == MPS_RES_OK) { res = reservoir_allocrone(&q, apamc, 10, MPS_RANK_EXACT); if (res == MPS_RES_OK) { setref(q, 0, p); p = q; } i++; } report("allocfail3", "%d", i); report_res("failres3", res); /* should be none left to make available */ mps_reservoir_limit_set(arena, 10ul*1024*1024); report("lim8", "%d", lim8 = mps_reservoir_limit(arena)); report("avail8", "%d", avail8 = mps_reservoir_available(arena)); report("commit8", "%d", commit8 = mps_arena_committed(arena)); report("spill8", "%d", commit8-mps_arena_commit_limit(arena)); /* throw away objects and collect world */ p = NULL; q = NULL; mps_root_destroy(root); mps_arena_collect(arena); /* available should have gone up now */ report("lim9", "%d", lim9 = mps_reservoir_limit(arena)); report("avail9", "%d", avail9 = mps_reservoir_available(arena)); report("commit9", "%d", commit9 = mps_arena_committed(arena)); report("grow9", "%d", avail9-avail8); report("spill9", "%d", commit9-mps_arena_commit_limit(arena)); /* destroy everything remaining */ mps_ap_destroy(apamc); comment("Destroyed ap."); mps_pool_destroy(poolamc); comment("Destroyed pool."); mps_fmt_destroy(format); comment("Destroyed format."); mps_thread_dereg(thread); comment("Deregistered thread."); mps_arena_destroy(arena); comment("Destroyed space."); }