diff options
author | sewardj <sewardj@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2008-05-02 13:35:29 +0000 |
---|---|---|
committer | sewardj <sewardj@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2008-05-02 13:35:29 +0000 |
commit | 9d624d16da5dc288258a8a6eae9201b5685359e0 (patch) | |
tree | cc0fd067dffdc050c4d351ee46fae41b1a34bd50 /memcheck/mc_main.c | |
parent | 7244e712e0c4ee18254fe7fa8e11352e6f3fd396 (diff) |
Dynamically allocate the origin tracking cache as needed (only for
runs with --track-origins=yes), rather than having it statically
allocated. This is important because the cache is large (100MB) and
soaking up 100MB of address space for a non-tracking run is not good.
Unfortunately this slows down the origin tracker by 1 to 2 %.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7989 a5019735-40e9-0310-863c-91ae7b9d1cf9
Diffstat (limited to 'memcheck/mc_main.c')
-rw-r--r-- | memcheck/mc_main.c | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index 63ef6c63..e462fce5 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -1896,16 +1896,24 @@ typedef } OCache; -static OCache ocache; -static UWord ocache_event_ctr = 0; +static OCache* ocache = NULL; +static UWord ocache_event_ctr = 0; static void init_ocacheL2 ( void ); /* fwds */ static void init_OCache ( void ) { UWord line, set; + tl_assert(MC_(clo_mc_level) >= 3); + tl_assert(ocache == NULL); + ocache = VG_(am_shadow_alloc)(sizeof(OCache)); + if (ocache == NULL) { + VG_(out_of_memory_NORETURN)( "memcheck:allocate the OCache", + sizeof(OCache) ); + } + tl_assert(ocache != NULL); for (set = 0; set < OC_N_SETS; set++) { for (line = 0; line < OC_LINES_PER_SET; line++) { - ocache.set[set].line[line].tag = 1/*invalid*/; + ocache->set[set].line[line].tag = 1/*invalid*/; } } init_ocacheL2(); @@ -2015,7 +2023,7 @@ static OCacheLine* find_OCacheLine_SLOW ( Addr a ) /* we already tried line == 0; skip therefore. */ for (line = 1; line < OC_LINES_PER_SET; line++) { - if (ocache.set[setno].line[line].tag == tag) { + if (ocache->set[setno].line[line].tag == tag) { if (line == 1) { stats_ocacheL1_found_at_1++; } else { @@ -2023,10 +2031,10 @@ static OCacheLine* find_OCacheLine_SLOW ( Addr a ) } if (UNLIKELY(0 == (ocache_event_ctr++ & ((1<<OC_MOVE_FORWARDS_EVERY_BITS)-1)))) { - moveLineForwards( &ocache.set[setno], line ); + moveLineForwards( &ocache->set[setno], line ); line--; } - return &ocache.set[setno].line[line]; + return &ocache->set[setno].line[line]; } } @@ -2038,7 +2046,7 @@ static OCacheLine* find_OCacheLine_SLOW ( Addr a ) tl_assert(line > 0); /* First, move the to-be-ejected line to the L2 cache. */ - victim = &ocache.set[setno].line[line]; + victim = &ocache->set[setno].line[line]; c = classify_OCacheLine(victim); switch (c) { case 'e': @@ -2073,19 +2081,19 @@ static OCacheLine* find_OCacheLine_SLOW ( Addr a ) inL2 = ocacheL2_find_tag( tag ); if (inL2) { /* We're in luck. It's in the L2. */ - ocache.set[setno].line[line] = *inL2; + ocache->set[setno].line[line] = *inL2; } else { /* Missed at both levels of the cache hierarchy. We have to declare it as full of zeroes (unknown origins). */ stats__ocacheL2_misses++; - zeroise_OCacheLine( &ocache.set[setno].line[line], tag ); + zeroise_OCacheLine( &ocache->set[setno].line[line], tag ); } /* Move it one forwards */ - moveLineForwards( &ocache.set[setno], line ); + moveLineForwards( &ocache->set[setno], line ); line--; - return &ocache.set[setno].line[line]; + return &ocache->set[setno].line[line]; } static INLINE OCacheLine* find_OCacheLine ( Addr a ) @@ -2101,8 +2109,8 @@ static INLINE OCacheLine* find_OCacheLine ( Addr a ) tl_assert(0 == (tag & (4 * OC_W32S_PER_LINE - 1))); } - if (LIKELY(ocache.set[setno].line[0].tag == tag)) { - return &ocache.set[setno].line[0]; + if (LIKELY(ocache->set[setno].line[0].tag == tag)) { + return &ocache->set[setno].line[0]; } return find_OCacheLine_SLOW( a ); @@ -5277,6 +5285,17 @@ static void mc_post_clo_init ( void ) # endif VG_(track_new_mem_stack) ( mc_new_mem_stack ); } + + /* This origin tracking cache is huge (~100M), so only initialise + if we need it. */ + if (MC_(clo_mc_level) >= 3) { + init_OCache(); + tl_assert(ocache != NULL); + tl_assert(ocacheL2 != NULL); + } else { + tl_assert(ocache == NULL); + tl_assert(ocacheL2 == NULL); + } } static void print_SM_info(char* type, int n_SMs) @@ -5396,6 +5415,9 @@ static void mc_fini ( Int exitcode ) VG_(message)(Vg_DebugMsg, " niacache: %,12lu refs %,12lu misses", stats__nia_cache_queries, stats__nia_cache_misses); + } else { + tl_assert(ocache == NULL); + tl_assert(ocacheL2 == NULL); } } @@ -5519,9 +5541,15 @@ static void mc_pre_clo_init(void) // BYTES_PER_SEC_VBIT_NODE must be a power of two. tl_assert(-1 != VG_(log2)(BYTES_PER_SEC_VBIT_NODE)); - init_OCache(); + /* This is small. Always initialise it. */ init_nia_to_ecu_cache(); + /* We can't initialise ocache/ocacheL2 yet, since we don't know if + we need to, since the command line args haven't been processed + yet. Hence defer it to mc_post_clo_init. */ + tl_assert(ocache == NULL); + tl_assert(ocacheL2 == NULL); + /* Check some important stuff. See extensive comments above re UNALIGNED_OR_HIGH for background. */ # if VG_WORDSIZE == 4 |