提交 9d4c9b5b 编写于 作者: A asaha

Merge

...@@ -768,6 +768,7 @@ d8be40462cfb6de441818aec8c30e03077189010 jdk8u66-b32 ...@@ -768,6 +768,7 @@ d8be40462cfb6de441818aec8c30e03077189010 jdk8u66-b32
6a0b19c56d797c2975f0cf505190e8f5d69b0b7a jdk8u66-b33 6a0b19c56d797c2975f0cf505190e8f5d69b0b7a jdk8u66-b33
3d55b1055c782375e39ebbddba2887379bc3531c jdk8u66-b34 3d55b1055c782375e39ebbddba2887379bc3531c jdk8u66-b34
95b0e04287fb443a4eee64504e0f18bc324c7abd jdk8u66-b35 95b0e04287fb443a4eee64504e0f18bc324c7abd jdk8u66-b35
dce99debdba26def128cd8b2d3eae93d7d789ee2 jdk8u66-b36
9a158a0c243beb610dbaabd63d6218d3ce5825f1 jdk8u71-b00 9a158a0c243beb610dbaabd63d6218d3ce5825f1 jdk8u71-b00
67df26e363fb7e722032fd286673642fc999957c jdk8u71-b01 67df26e363fb7e722032fd286673642fc999957c jdk8u71-b01
1a799d49de23d84f658ade1d3805a1924e7e1e84 jdk8u71-b02 1a799d49de23d84f658ade1d3805a1924e7e1e84 jdk8u71-b02
......
...@@ -178,75 +178,6 @@ extern "C" { ...@@ -178,75 +178,6 @@ extern "C" {
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); 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) { static inline size_t adjust_stack_size(address base, size_t size) {
if ((ssize_t)size < 0) { if ((ssize_t)size < 0) {
// 4759953: Compensate for ridiculous stack size. // 4759953: Compensate for ridiculous stack size.
...@@ -1473,64 +1404,6 @@ int os::current_process_id() { ...@@ -1473,64 +1404,6 @@ int os::current_process_id() {
return (int)(_initial_pid ? _initial_pid : getpid()); 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");
}
#define SMALLINT 32 // libthread allocate for tsd_common is a version specific
// small number - point is NO swap space available
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, // gethrtime() should be monotonic according to the documentation,
// but some virtualized platforms are known to break this guarantee. // but some virtualized platforms are known to break this guarantee.
// getTimeNanos() must be guaranteed not to move backwards, so we // getTimeNanos() must be guaranteed not to move backwards, so we
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 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
...@@ -40,19 +40,12 @@ ...@@ -40,19 +40,12 @@
// For SPARC, to avoid excessive register window spill-fill faults, // For SPARC, to avoid excessive register window spill-fill faults,
// we aggressively inline these routines. // we aggressively inline these routines.
inline Thread* ThreadLocalStorage::thread() { inline void ThreadLocalStorage::set_thread(Thread* thread) {
// don't use specialized code if +UseMallocOnly -- may confuse Purify et al. _thr_current = thread;
debug_only(if (UseMallocOnly) return get_thread_slow();); }
uintptr_t raw = pd_raw_thread_id(); inline Thread* ThreadLocalStorage::thread() {
int ix = pd_cache_index(raw); return _thr_current;
Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix];
if (candidate->self_raw_id() == raw) {
// hit
return candidate;
} else {
return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix);
}
} }
#endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP #endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 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
...@@ -26,19 +26,26 @@ ...@@ -26,19 +26,26 @@
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp" #include "runtime/threadLocalStorage.hpp"
// Provides an entry point we can link against and // True thread-local variable
// a buffer we can emit code into. The buffer is __thread Thread * ThreadLocalStorage::_thr_current = NULL;
// filled by ThreadLocalStorage::generate_code_for_get_thread
// and called from ThreadLocalStorage::thread()
#include <sys/systeminfo.h> // Implementations needed to support the shared API
// The portable TLS mechanism (get_thread_via_cache) is enough on SPARC. void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
// There is no need for hand-assembling a special function.
void ThreadLocalStorage::generate_code_for_get_thread() { bool ThreadLocalStorage::_initialized = false;
void ThreadLocalStorage::init() {
_initialized = true;
} }
void ThreadLocalStorage::set_thread_in_slot (Thread * self) {} bool ThreadLocalStorage::is_initialized() {
return _initialized;
}
Thread* ThreadLocalStorage::get_thread_slow() {
return thread();
}
extern "C" Thread* get_thread() { extern "C" Thread* get_thread() {
return ThreadLocalStorage::thread(); return ThreadLocalStorage::thread();
......
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 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
...@@ -25,47 +25,15 @@ ...@@ -25,47 +25,15 @@
#ifndef OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP #ifndef OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
#define OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP #define OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
public: // Solaris specific implementation involves simple, direct use
// Java Thread - force inlining // of a compiler-based thread-local variable
static inline Thread* thread() ;
private: private:
static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size] static __thread Thread * _thr_current;
static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index);
NOT_PRODUCT(static int _tcacheHit;) static bool _initialized; // needed for shared API
NOT_PRODUCT(static int _tcacheMiss;)
public: public:
static inline Thread* thread();
// Print cache hit/miss statistics
static void print_statistics() PRODUCT_RETURN;
enum Constants {
_pd_cache_size = 256*2 // projected typical # of threads * 2
};
static void set_thread_in_slot (Thread *) ;
static uintptr_t pd_raw_thread_id() {
return _raw_thread_id();
}
static int pd_cache_index(uintptr_t raw_id) {
// Hash function: From email from Dave:
// The hash function deserves an explanation. %g7 points to libthread's
// "thread" structure. On T1 the thread structure is allocated on the
// user's stack (yes, really!) so the ">>20" handles T1 where the JVM's
// stack size is usually >= 1Mb. The ">>9" is for T2 where Roger allocates
// globs of thread blocks contiguously. The "9" has to do with the
// expected size of the T2 thread structure. If these constants are wrong
// the worst thing that'll happen is that the hit rate for heavily threaded
// apps won't be as good as it could be. If you want to burn another
// shift+xor you could mix together _all of the %g7 bits to form the hash,
// but I think that's excessive. Making the change above changed the
// T$ miss rate on SpecJBB (on a 16X system) from about 3% to imperceptible.
uintptr_t ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size);
return ix;
}
#endif // OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP #endif // OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 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
...@@ -23,11 +23,10 @@ ...@@ -23,11 +23,10 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp" #include "asm/macroAssembler.inline.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "runtime/threadLocalStorage.hpp" #include "runtime/threadLocalStorage.hpp"
#include "runtime/thread.inline.hpp"
void MacroAssembler::int3() { void MacroAssembler::int3() {
push(rax); push(rax);
...@@ -39,98 +38,32 @@ void MacroAssembler::int3() { ...@@ -39,98 +38,32 @@ void MacroAssembler::int3() {
pop(rax); pop(rax);
} }
#define __ _masm-> // This is simply a call to ThreadLocalStorage::thread()
#ifndef _LP64 void MacroAssembler::get_thread(Register thread) {
static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) {
// slow call to of thr_getspecific
// int thr_getspecific(thread_key_t key, void **value);
// Consider using pthread_getspecific instead.
__ push(0); // allocate space for return value
if (thread != rax) __ push(rax); // save rax, if caller still wants it
__ push(rcx); // save caller save
__ push(rdx); // save caller save
if (thread != rax) {
__ lea(thread, Address(rsp, 3 * sizeof(int))); // address of return value
} else {
__ lea(thread, Address(rsp, 2 * sizeof(int))); // address of return value
}
__ push(thread); // and pass the address
__ push(ThreadLocalStorage::thread_index()); // the key
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific)));
__ increment(rsp, 2 * wordSize);
__ pop(rdx);
__ pop(rcx);
if (thread != rax) __ pop(rax);
__ pop(thread);
}
#else
static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) {
// slow call to of thr_getspecific
// int thr_getspecific(thread_key_t key, void **value);
// Consider using pthread_getspecific instead.
if (thread != rax) { if (thread != rax) {
__ push(rax); push(rax);
} }
__ push(0); // space for return value push(rdi);
__ push(rdi); push(rsi);
__ push(rsi); push(rdx);
__ lea(rsi, Address(rsp, 16)); // pass return value address push(rcx);
__ push(rdx); push(r8);
__ push(rcx); push(r9);
__ push(r8); push(r10);
__ push(r9); push(r11);
__ push(r10);
// XXX
__ mov(r10, rsp);
__ andptr(rsp, -16);
__ push(r10);
__ push(r11);
__ movl(rdi, ThreadLocalStorage::thread_index()); call(RuntimeAddress(CAST_FROM_FN_PTR(address, ThreadLocalStorage::thread)));
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific)));
__ pop(r11); pop(r11);
__ pop(rsp); pop(r10);
__ pop(r10); pop(r9);
__ pop(r9); pop(r8);
__ pop(r8); pop(rcx);
__ pop(rcx); pop(rdx);
__ pop(rdx); pop(rsi);
__ pop(rsi); pop(rdi);
__ pop(rdi);
__ pop(thread); // load return value
if (thread != rax) { if (thread != rax) {
__ pop(rax); movl(thread, rax);
} pop(rax);
}
#endif //LP64
void MacroAssembler::get_thread(Register thread) {
int segment = NOT_LP64(Assembler::GS_segment) LP64_ONLY(Assembler::FS_segment);
// Try to emit a Solaris-specific fast TSD/TLS accessor.
ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_getTlsAccessMode ();
if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) { // T1
// Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset]
emit_int8 (segment);
// ExternalAddress doesn't work because it can't take NULL
AddressLiteral null(0, relocInfo::none);
movptr (thread, null);
movptr(thread, Address(thread, ThreadLocalStorage::pd_getTlsOffset())) ;
return ;
} else
if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2
// mov r, gs:[tlsOffset]
emit_int8 (segment);
AddressLiteral tls_off((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none);
movptr (thread, tls_off);
return ;
} }
slow_call_thr_specific(this, thread);
} }
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 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
...@@ -26,167 +26,27 @@ ...@@ -26,167 +26,27 @@
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp" #include "runtime/threadLocalStorage.hpp"
#ifdef AMD64 // True thread-local variable
extern "C" Thread* fs_load(ptrdiff_t tlsOffset); __thread Thread * ThreadLocalStorage::_thr_current = NULL;
extern "C" intptr_t fs_thread();
#else
// From solaris_i486.s
extern "C" Thread* gs_load(ptrdiff_t tlsOffset);
extern "C" intptr_t gs_thread();
#endif // AMD64
// tlsMode encoding: // Implementations needed to support the shared API
//
// pd_tlsAccessUndefined : uninitialized
// pd_tlsAccessSlow : not available
// pd_tlsAccessIndirect :
// old-style indirect access - present in "T1" libthread.
// use thr_slot_sync_allocate() to attempt to allocate a slot.
// pd_tlsAccessDirect :
// new-style direct access - present in late-model "T2" libthread.
// Allocate the offset (slot) via _thr_slot_offset() or by
// defining an IE- or LE-mode TLS/TSD slot in the launcher and then passing
// that offset into libjvm.so.
// See http://sac.eng/Archives/CaseLog/arc/PSARC/2003/159/.
//
// Note that we have a capability gap - some early model T2 forms
// (e.g., unpatched S9) have neither _thr_slot_sync_allocate() nor
// _thr_slot_offset(). In that case we revert to the usual
// thr_getspecific accessor.
//
static ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_tlsAccessUndefined ; void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
static ptrdiff_t tlsOffset = 0 ;
static thread_key_t tlsKey ;
typedef int (*TSSA_Entry) (ptrdiff_t *, int, int) ; bool ThreadLocalStorage::_initialized = false;
typedef ptrdiff_t (*TSO_Entry) (int) ;
ThreadLocalStorage::pd_tlsAccessMode ThreadLocalStorage::pd_getTlsAccessMode () void ThreadLocalStorage::init() {
{ _initialized = true;
guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
return tlsMode ;
} }
ptrdiff_t ThreadLocalStorage::pd_getTlsOffset () { bool ThreadLocalStorage::is_initialized() {
guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; return _initialized;
return tlsOffset ;
} }
// TODO: Consider the following improvements: Thread* ThreadLocalStorage::get_thread_slow() {
// return thread();
// 1. Convert from thr_*specific* to pthread_*specific*.
// The pthread_ forms are slightly faster. Also, the
// pthread_ forms have a pthread_key_delete() API which
// would aid in clean JVM shutdown and the eventual goal
// of permitting a JVM to reinstantiate itself withing a process.
//
// 2. See ThreadLocalStorage::init(). We end up allocating
// two TLS keys during VM startup. That's benign, but we could collapse
// down to one key without too much trouble.
//
// 3. MacroAssembler::get_thread() currently emits calls to thr_getspecific().
// Modify get_thread() to call Thread::current() instead.
//
// 4. Thread::current() currently uses a cache keyed by %gs:[0].
// (The JVM has PSARC permission to use %g7/%gs:[0]
// as an opaque temporally unique thread identifier).
// For C++ access to a thread's reflexive "self" pointer we
// should consider using one of the following:
// a. a radix tree keyed by %esp - as in EVM.
// This requires two loads (the 2nd dependent on the 1st), but
// is easily inlined and doesn't require a "miss" slow path.
// b. a fast TLS/TSD slot allocated by _thr_slot_offset
// or _thr_slot_sync_allocate.
//
// 5. 'generate_code_for_get_thread' is a misnomer.
// We should change it to something more general like
// pd_ThreadSelf_Init(), for instance.
//
static void AllocateTLSOffset ()
{
int rslt ;
TSSA_Entry tssa ;
TSO_Entry tso ;
ptrdiff_t off ;
guarantee (tlsMode == ThreadLocalStorage::pd_tlsAccessUndefined, "tlsMode not set") ;
tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
tlsOffset = 0 ;
#ifndef AMD64
tssa = (TSSA_Entry) dlsym (RTLD_DEFAULT, "thr_slot_sync_allocate") ;
if (tssa != NULL) {
off = -1 ;
rslt = (*tssa)(&off, NULL, NULL) ; // (off,dtor,darg)
if (off != -1) {
tlsOffset = off ;
tlsMode = ThreadLocalStorage::pd_tlsAccessIndirect ;
return ;
}
}
rslt = thr_keycreate (&tlsKey, NULL) ;
if (rslt != 0) {
tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; // revert to slow mode
return ;
}
tso = (TSO_Entry) dlsym (RTLD_DEFAULT, "_thr_slot_offset") ;
if (tso != NULL) {
off = (*tso)(tlsKey) ;
if (off >= 0) {
tlsOffset = off ;
tlsMode = ThreadLocalStorage::pd_tlsAccessDirect ;
return ;
}
}
// Failure: Too bad ... we've allocated a TLS slot we don't need and there's
// no provision in the ABI for returning the slot.
//
// If we didn't find a slot then then:
// 1. We might be on liblwp.
// 2. We might be on T2 libthread, but all "fast" slots are already
// consumed
// 3. We might be on T1, and all TSD (thr_slot_sync_allocate) slots are
// consumed.
// 4. We might be on T2 libthread, but it's be re-architected
// so that fast slots are no longer g7-relative.
//
tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
return ;
#endif // AMD64
}
void ThreadLocalStorage::generate_code_for_get_thread() {
AllocateTLSOffset() ;
} }
void ThreadLocalStorage::set_thread_in_slot(Thread *thread) {
guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
if (tlsMode == pd_tlsAccessIndirect) {
#ifdef AMD64
intptr_t tbase = fs_thread();
#else
intptr_t tbase = gs_thread();
#endif // AMD64
*((Thread**) (tbase + tlsOffset)) = thread ;
} else
if (tlsMode == pd_tlsAccessDirect) {
thr_setspecific (tlsKey, (void *) thread) ;
// set with thr_setspecific and then readback with gs_load to validate.
#ifdef AMD64
guarantee (thread == fs_load(tlsOffset), "tls readback failure") ;
#else
guarantee (thread == gs_load(tlsOffset), "tls readback failure") ;
#endif // AMD64
}
}
extern "C" Thread* get_thread() { extern "C" Thread* get_thread() {
return ThreadLocalStorage::thread(); return ThreadLocalStorage::thread();
} }
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 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
...@@ -25,61 +25,15 @@ ...@@ -25,61 +25,15 @@
#ifndef OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP #ifndef OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
#define OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP #define OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
// Processor dependent parts of ThreadLocalStorage // Solaris specific implementation involves simple, direct use
// of a compiler-based thread-local variable
private: private:
static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size] static __thread Thread * _thr_current;
static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index);
NOT_PRODUCT(static int _tcacheHit;) static bool _initialized; // needed for shared API
NOT_PRODUCT(static int _tcacheMiss;)
public: public:
// Cache hit/miss statistics
static void print_statistics() PRODUCT_RETURN;
enum Constants {
#ifdef AMD64
_pd_cache_size = 256*2 // projected typical # of threads * 2
#else
_pd_cache_size = 128*2 // projected typical # of threads * 2
#endif // AMD64
};
enum pd_tlsAccessMode {
pd_tlsAccessUndefined = -1,
pd_tlsAccessSlow = 0,
pd_tlsAccessIndirect = 1,
pd_tlsAccessDirect = 2
} ;
static void set_thread_in_slot (Thread *) ;
static pd_tlsAccessMode pd_getTlsAccessMode () ;
static ptrdiff_t pd_getTlsOffset () ;
static uintptr_t pd_raw_thread_id() {
#ifdef _GNU_SOURCE
#ifdef AMD64
uintptr_t rv;
__asm__ __volatile__ ("movq %%fs:0, %0" : "=r"(rv));
return rv;
#else
return gs_thread();
#endif // AMD64
#else //_GNU_SOURCE
return _raw_thread_id();
#endif //_GNU_SOURCE
}
static int pd_cache_index(uintptr_t raw_id) {
// Copied from the sparc version. Dave said it should also work fine
// for solx86.
int ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size);
return ix;
}
// Java Thread
static inline Thread* thread(); static inline Thread* thread();
#endif // OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP #endif // OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
/* /*
* Copyright (c) 1997, 2010, 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
...@@ -38,6 +38,11 @@ ...@@ -38,6 +38,11 @@
# include "os_bsd.inline.hpp" # include "os_bsd.inline.hpp"
#endif #endif
// Solaris no longer has this kind of ThreadLocalStorage implementation.
// This will be removed from all platforms in the near future.
#ifndef SOLARIS
// static member initialization // static member initialization
int ThreadLocalStorage::_thread_index = -1; int ThreadLocalStorage::_thread_index = -1;
...@@ -65,3 +70,5 @@ void ThreadLocalStorage::init() { ...@@ -65,3 +70,5 @@ void ThreadLocalStorage::init() {
bool ThreadLocalStorage::is_initialized() { bool ThreadLocalStorage::is_initialized() {
return (thread_index() != -1); return (thread_index() != -1);
} }
#endif // SOLARIS
...@@ -38,10 +38,14 @@ extern "C" Thread* get_thread(); ...@@ -38,10 +38,14 @@ extern "C" Thread* get_thread();
extern "C" uintptr_t _raw_thread_id(); extern "C" uintptr_t _raw_thread_id();
class ThreadLocalStorage : AllStatic { class ThreadLocalStorage : AllStatic {
// Exported API
public: public:
static void set_thread(Thread* thread); static void set_thread(Thread* thread);
static Thread* get_thread_slow(); static Thread* get_thread_slow();
static void invalidate_all() { pd_invalidate_all(); } static void invalidate_all() { pd_invalidate_all(); }
static void init();
static bool is_initialized();
// Machine dependent stuff // Machine dependent stuff
#ifdef TARGET_OS_ARCH_linux_x86 #ifdef TARGET_OS_ARCH_linux_x86
...@@ -78,17 +82,12 @@ class ThreadLocalStorage : AllStatic { ...@@ -78,17 +82,12 @@ class ThreadLocalStorage : AllStatic {
# include "threadLS_bsd_zero.hpp" # include "threadLS_bsd_zero.hpp"
#endif #endif
#ifndef SOLARIS
public: public:
// Accessor // Accessor
static inline int thread_index() { return _thread_index; } static inline int thread_index() { return _thread_index; }
static inline void set_thread_index(int index) { _thread_index = index; } static inline void set_thread_index(int index) { _thread_index = index; }
// Initialization
// Called explicitly from VMThread::activate_system instead of init_globals.
static void init();
static bool is_initialized();
private: private:
static int _thread_index; static int _thread_index;
...@@ -97,6 +96,9 @@ class ThreadLocalStorage : AllStatic { ...@@ -97,6 +96,9 @@ class ThreadLocalStorage : AllStatic {
// Processor dependent parts of set_thread and initialization // Processor dependent parts of set_thread and initialization
static void pd_set_thread(Thread* thread); static void pd_set_thread(Thread* thread);
static void pd_init(); static void pd_init();
#endif // SOLARIS
// Invalidate any thread cacheing or optimization schemes. // Invalidate any thread cacheing or optimization schemes.
static void pd_invalidate_all(); static void pd_invalidate_all();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册