8068451: Kitchensink fails with assert(_size >= sz) failed: Negative size
Need ThreadCritical lock around chunk pool cleaning and copying for snapshot Reviewed-by: lfoltan, gtriantafill, hseigel
This commit is contained in:
parent
cc1c11c366
commit
8df6ac1794
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -287,19 +287,18 @@ class ChunkPool: public CHeapObj<mtInternal> {
|
|||||||
cur->set_next(NULL);
|
cur->set_next(NULL);
|
||||||
cur = next;
|
cur = next;
|
||||||
|
|
||||||
_num_chunks = n;
|
// Free all remaining chunks while in ThreadCritical lock
|
||||||
}
|
// so NMT adjustment is stable.
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free all remaining chunks, outside of ThreadCritical
|
|
||||||
// to avoid deadlock with NMT
|
|
||||||
while(cur != NULL) {
|
while(cur != NULL) {
|
||||||
next = cur->next();
|
next = cur->next();
|
||||||
os::free(cur);
|
os::free(cur);
|
||||||
|
_num_chunks--;
|
||||||
cur = next;
|
cur = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Accessors to preallocated pool's
|
// Accessors to preallocated pool's
|
||||||
static ChunkPool* large_pool() { assert(_large_pool != NULL, "must be initialized"); return _large_pool; }
|
static ChunkPool* large_pool() { assert(_large_pool != NULL, "must be initialized"); return _large_pool; }
|
||||||
@ -384,7 +383,9 @@ void Chunk::operator delete(void* p) {
|
|||||||
case Chunk::medium_size: ChunkPool::medium_pool()->free(c); break;
|
case Chunk::medium_size: ChunkPool::medium_pool()->free(c); break;
|
||||||
case Chunk::init_size: ChunkPool::small_pool()->free(c); break;
|
case Chunk::init_size: ChunkPool::small_pool()->free(c); break;
|
||||||
case Chunk::tiny_size: ChunkPool::tiny_pool()->free(c); break;
|
case Chunk::tiny_size: ChunkPool::tiny_pool()->free(c); break;
|
||||||
default: os::free(c);
|
default:
|
||||||
|
ThreadCritical tc; // Free chunks under TC lock so that NMT adjustment is stable.
|
||||||
|
os::free(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ bool MallocSiteTable::walk(MallocSiteWalker* walker) {
|
|||||||
MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx,
|
MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx,
|
||||||
size_t* pos_idx) {
|
size_t* pos_idx) {
|
||||||
int index = hash_to_index(key.hash());
|
int index = hash_to_index(key.hash());
|
||||||
assert(index >= 0, "Negative index");
|
assert(index >= 0, err_msg("Negative index %d", index));
|
||||||
*bucket_idx = (size_t)index;
|
*bucket_idx = (size_t)index;
|
||||||
*pos_idx = 0;
|
*pos_idx = 0;
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ size_t MallocMemorySnapshot::total_arena() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make adjustment by subtracting chunks used by arenas
|
// Make adjustment by subtracting chunks used by arenas
|
||||||
// from total chunks to get total free chunck size
|
// from total chunks to get total free chunk size
|
||||||
void MallocMemorySnapshot::make_adjustment() {
|
void MallocMemorySnapshot::make_adjustment() {
|
||||||
size_t arena_size = total_arena();
|
size_t arena_size = total_arena();
|
||||||
int chunk_idx = NMTUtil::flag_to_index(mtChunk);
|
int chunk_idx = NMTUtil::flag_to_index(mtChunk);
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
|
#include "runtime/threadCritical.hpp"
|
||||||
#include "services/nmtCommon.hpp"
|
#include "services/nmtCommon.hpp"
|
||||||
#include "utilities/nativeCallStack.hpp"
|
#include "utilities/nativeCallStack.hpp"
|
||||||
|
|
||||||
@ -164,6 +165,10 @@ class MallocMemorySnapshot : public ResourceObj {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void copy_to(MallocMemorySnapshot* s) {
|
void copy_to(MallocMemorySnapshot* s) {
|
||||||
|
// Need to make sure that mtChunks don't get deallocated while the
|
||||||
|
// copy is going on, because their size is adjusted using this
|
||||||
|
// buffer in make_adjustment().
|
||||||
|
ThreadCritical tc;
|
||||||
s->_tracking_header = _tracking_header;
|
s->_tracking_header = _tracking_header;
|
||||||
for (int index = 0; index < mt_number_of_types; index ++) {
|
for (int index = 0; index < mt_number_of_types; index ++) {
|
||||||
s->_malloc[index] = _malloc[index];
|
s->_malloc[index] = _malloc[index];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
Loading…
Reference in New Issue
Block a user