mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
8130212: Thread::current() might access freed memory on Solaris
Reviewed-by: kvn, twisti, stuefe
This commit is contained in:
parent
0b408e7136
commit
47dd02d847
9 changed files with 88 additions and 494 deletions
|
@ -182,75 +182,6 @@ extern "C" {
|
|||
|
||||
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
|
||||
|
||||
// Thread Local Storage
|
||||
// This is common to all Solaris platforms so it is defined here,
|
||||
// in this common file.
|
||||
// The declarations are in the os_cpu threadLS*.hpp files.
|
||||
//
|
||||
// Static member initialization for TLS
|
||||
Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL};
|
||||
|
||||
#ifndef PRODUCT
|
||||
#define _PCT(n,d) ((100.0*(double)(n))/(double)(d))
|
||||
|
||||
int ThreadLocalStorage::_tcacheHit = 0;
|
||||
int ThreadLocalStorage::_tcacheMiss = 0;
|
||||
|
||||
void ThreadLocalStorage::print_statistics() {
|
||||
int total = _tcacheMiss+_tcacheHit;
|
||||
tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n",
|
||||
_tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total));
|
||||
}
|
||||
#undef _PCT
|
||||
#endif // PRODUCT
|
||||
|
||||
Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id,
|
||||
int index) {
|
||||
Thread *thread = get_thread_slow();
|
||||
if (thread != NULL) {
|
||||
address sp = os::current_stack_pointer();
|
||||
guarantee(thread->_stack_base == NULL ||
|
||||
(sp <= thread->_stack_base &&
|
||||
sp >= thread->_stack_base - thread->_stack_size) ||
|
||||
is_error_reported(),
|
||||
"sp must be inside of selected thread stack");
|
||||
|
||||
thread->set_self_raw_id(raw_id); // mark for quick retrieval
|
||||
_get_thread_cache[index] = thread;
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
|
||||
static const double all_zero[sizeof(Thread) / sizeof(double) + 1] = {0};
|
||||
#define NO_CACHED_THREAD ((Thread*)all_zero)
|
||||
|
||||
void ThreadLocalStorage::pd_set_thread(Thread* thread) {
|
||||
|
||||
// Store the new value before updating the cache to prevent a race
|
||||
// between get_thread_via_cache_slowly() and this store operation.
|
||||
os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
|
||||
|
||||
// Update thread cache with new thread if setting on thread create,
|
||||
// or NO_CACHED_THREAD (zeroed) thread if resetting thread on exit.
|
||||
uintptr_t raw = pd_raw_thread_id();
|
||||
int ix = pd_cache_index(raw);
|
||||
_get_thread_cache[ix] = thread == NULL ? NO_CACHED_THREAD : thread;
|
||||
}
|
||||
|
||||
void ThreadLocalStorage::pd_init() {
|
||||
for (int i = 0; i < _pd_cache_size; i++) {
|
||||
_get_thread_cache[i] = NO_CACHED_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate all the caches (happens to be the same as pd_init).
|
||||
void ThreadLocalStorage::pd_invalidate_all() { pd_init(); }
|
||||
|
||||
#undef NO_CACHED_THREAD
|
||||
|
||||
// END Thread Local Storage
|
||||
|
||||
static inline size_t adjust_stack_size(address base, size_t size) {
|
||||
if ((ssize_t)size < 0) {
|
||||
// 4759953: Compensate for ridiculous stack size.
|
||||
|
@ -1289,67 +1220,6 @@ int os::current_process_id() {
|
|||
return (int)(_initial_pid ? _initial_pid : getpid());
|
||||
}
|
||||
|
||||
int os::allocate_thread_local_storage() {
|
||||
// %%% in Win32 this allocates a memory segment pointed to by a
|
||||
// register. Dan Stein can implement a similar feature in
|
||||
// Solaris. Alternatively, the VM can do the same thing
|
||||
// explicitly: malloc some storage and keep the pointer in a
|
||||
// register (which is part of the thread's context) (or keep it
|
||||
// in TLS).
|
||||
// %%% In current versions of Solaris, thr_self and TSD can
|
||||
// be accessed via short sequences of displaced indirections.
|
||||
// The value of thr_self is available as %g7(36).
|
||||
// The value of thr_getspecific(k) is stored in %g7(12)(4)(k*4-4),
|
||||
// assuming that the current thread already has a value bound to k.
|
||||
// It may be worth experimenting with such access patterns,
|
||||
// and later having the parameters formally exported from a Solaris
|
||||
// interface. I think, however, that it will be faster to
|
||||
// maintain the invariant that %g2 always contains the
|
||||
// JavaThread in Java code, and have stubs simply
|
||||
// treat %g2 as a caller-save register, preserving it in a %lN.
|
||||
thread_key_t tk;
|
||||
if (thr_keycreate(&tk, NULL)) {
|
||||
fatal(err_msg("os::allocate_thread_local_storage: thr_keycreate failed "
|
||||
"(%s)", strerror(errno)));
|
||||
}
|
||||
return int(tk);
|
||||
}
|
||||
|
||||
void os::free_thread_local_storage(int index) {
|
||||
// %%% don't think we need anything here
|
||||
// if (pthread_key_delete((pthread_key_t) tk)) {
|
||||
// fatal("os::free_thread_local_storage: pthread_key_delete failed");
|
||||
// }
|
||||
}
|
||||
|
||||
// libthread allocate for tsd_common is a version specific
|
||||
// small number - point is NO swap space available
|
||||
#define SMALLINT 32
|
||||
void os::thread_local_storage_at_put(int index, void* value) {
|
||||
// %%% this is used only in threadLocalStorage.cpp
|
||||
if (thr_setspecific((thread_key_t)index, value)) {
|
||||
if (errno == ENOMEM) {
|
||||
vm_exit_out_of_memory(SMALLINT, OOM_MALLOC_ERROR,
|
||||
"thr_setspecific: out of swap space");
|
||||
} else {
|
||||
fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed "
|
||||
"(%s)", strerror(errno)));
|
||||
}
|
||||
} else {
|
||||
ThreadLocalStorage::set_thread_in_slot((Thread *) value);
|
||||
}
|
||||
}
|
||||
|
||||
// This function could be called before TLS is initialized, for example, when
|
||||
// VM receives an async signal or when VM causes a fatal error during
|
||||
// initialization. Return NULL if thr_getspecific() fails.
|
||||
void* os::thread_local_storage_at(int index) {
|
||||
// %%% this is used only in threadLocalStorage.cpp
|
||||
void* r = NULL;
|
||||
return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r;
|
||||
}
|
||||
|
||||
|
||||
// gethrtime() should be monotonic according to the documentation,
|
||||
// but some virtualized platforms are known to break this guarantee.
|
||||
// getTimeNanos() must be guaranteed not to move backwards, so we
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue