Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
3279e351
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
3279e351
编写于
12月 07, 2015
作者:
D
dholmes
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8130212: Thread::current() might access freed memory on Solaris
Reviewed-by: kvn, twisti, stuefe
上级
d2340ea0
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
86 addition
and
489 deletion
+86
-489
src/os/solaris/vm/os_solaris.cpp
src/os/solaris/vm/os_solaris.cpp
+0
-127
src/os/solaris/vm/thread_solaris.inline.hpp
src/os/solaris/vm/thread_solaris.inline.hpp
+6
-13
src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp
src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp
+17
-10
src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp
src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp
+6
-38
src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp
src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp
+24
-91
src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp
src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp
+12
-152
src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp
src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp
+5
-51
src/share/vm/runtime/threadLocalStorage.cpp
src/share/vm/runtime/threadLocalStorage.cpp
+8
-1
src/share/vm/runtime/threadLocalStorage.hpp
src/share/vm/runtime/threadLocalStorage.hpp
+8
-6
未找到文件。
src/os/solaris/vm/os_solaris.cpp
浏览文件 @
3279e351
...
...
@@ -178,75 +178,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.
...
...
@@ -1473,64 +1404,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");
}
#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,
// but some virtualized platforms are known to break this guarantee.
// getTimeNanos() must be guaranteed not to move backwards, so we
...
...
src/os/solaris/vm/thread_solaris.inline.hpp
浏览文件 @
3279e351
/*
* Copyright (c) 2002, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 201
5
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -40,19 +40,12 @@
// For SPARC, to avoid excessive register window spill-fill faults,
// we aggressively inline these routines.
inline
Thread
*
ThreadLocalStorage
::
thread
()
{
// don't use specialized code if +UseMallocOnly -- may confuse Purify et al.
debug_only
(
if
(
UseMallocOnly
)
return
get_thread_slow
(););
inline
void
ThreadLocalStorage
::
set_thread
(
Thread
*
thread
)
{
_thr_current
=
thread
;
}
uintptr_t
raw
=
pd_raw_thread_id
();
int
ix
=
pd_cache_index
(
raw
);
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
);
}
inline
Thread
*
ThreadLocalStorage
::
thread
()
{
return
_thr_current
;
}
#endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP
src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp
浏览文件 @
3279e351
/*
* Copyright (c) 1998, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
5
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -26,19 +26,26 @@
#include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp"
// Provides an entry point we can link against and
// a buffer we can emit code into. The buffer is
// filled by ThreadLocalStorage::generate_code_for_get_thread
// and called from ThreadLocalStorage::thread()
// True thread-local variable
__thread
Thread
*
ThreadLocalStorage
::
_thr_current
=
NULL
;
#include <sys/systeminfo.h>
// Implementations needed to support the shared API
// The portable TLS mechanism (get_thread_via_cache) is enough on SPARC.
// There is no need for hand-assembling a special function.
void
ThreadLocalStorage
::
generate_code_for_get_thread
()
{
void
ThreadLocalStorage
::
pd_invalidate_all
()
{}
// nothing to do
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
()
{
return
ThreadLocalStorage
::
thread
();
...
...
src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp
浏览文件 @
3279e351
/*
* Copyright (c) 1998, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
5
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -25,47 +25,15 @@
#ifndef OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
#define OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
public
:
// Java Thread - force inlining
static
inline
Thread
*
thread
()
;
// Solaris specific implementation involves simple, direct use
// of a compiler-based thread-local variable
private
:
static
Thread
*
_get_thread_cache
[];
// index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size]
static
Thread
*
get_thread_via_cache_slowly
(
uintptr_t
raw_id
,
int
index
);
static
__thread
Thread
*
_thr_current
;
NOT_PRODUCT
(
static
int
_tcacheHit
;)
NOT_PRODUCT
(
static
int
_tcacheMiss
;)
static
bool
_initialized
;
// needed for shared API
public
:
// 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
;
}
static
inline
Thread
*
thread
();
#endif // OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp
浏览文件 @
3279e351
/*
* Copyright (c) 1999, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 201
5
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -23,11 +23,10 @@
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "runtime/thread.inline.hpp"
void
MacroAssembler
::
int3
()
{
push
(
rax
);
...
...
@@ -39,98 +38,32 @@ void MacroAssembler::int3() {
pop
(
rax
);
}
#define __ _masm->
#ifndef _LP64
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.
// This is simply a call to ThreadLocalStorage::thread()
void
MacroAssembler
::
get_thread
(
Register
thread
)
{
if
(
thread
!=
rax
)
{
__
push
(
rax
);
push
(
rax
);
}
__
push
(
0
);
// space for return value
__
push
(
rdi
);
__
push
(
rsi
);
__
lea
(
rsi
,
Address
(
rsp
,
16
));
// pass return value address
__
push
(
rdx
);
__
push
(
rcx
);
__
push
(
r8
);
__
push
(
r9
);
__
push
(
r10
);
// XXX
__
mov
(
r10
,
rsp
);
__
andptr
(
rsp
,
-
16
);
__
push
(
r10
);
__
push
(
r11
);
push
(
rdi
);
push
(
rsi
);
push
(
rdx
);
push
(
rcx
);
push
(
r8
);
push
(
r9
);
push
(
r10
);
push
(
r11
);
__
movl
(
rdi
,
ThreadLocalStorage
::
thread_index
());
__
call
(
RuntimeAddress
(
CAST_FROM_FN_PTR
(
address
,
thr_getspecific
)));
call
(
RuntimeAddress
(
CAST_FROM_FN_PTR
(
address
,
ThreadLocalStorage
::
thread
)));
__
pop
(
r11
);
__
pop
(
rsp
);
__
pop
(
r10
);
__
pop
(
r9
);
__
pop
(
r8
);
__
pop
(
rcx
);
__
pop
(
rdx
);
__
pop
(
rsi
);
__
pop
(
rdi
);
__
pop
(
thread
);
// load return value
pop
(
r11
);
pop
(
r10
);
pop
(
r9
);
pop
(
r8
);
pop
(
rcx
);
pop
(
rdx
);
pop
(
rsi
);
pop
(
rdi
);
if
(
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
;
movl
(
thread
,
rax
);
pop
(
rax
);
}
slow_call_thr_specific
(
this
,
thread
);
}
src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp
浏览文件 @
3279e351
/*
* Copyright (c) 1998, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
5
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -26,167 +26,27 @@
#include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp"
#ifdef AMD64
extern
"C"
Thread
*
fs_load
(
ptrdiff_t
tlsOffset
);
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
// True thread-local variable
__thread
Thread
*
ThreadLocalStorage
::
_thr_current
=
NULL
;
// tlsMode encoding:
//
// 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.
//
// Implementations needed to support the shared API
static
ThreadLocalStorage
::
pd_tlsAccessMode
tlsMode
=
ThreadLocalStorage
::
pd_tlsAccessUndefined
;
static
ptrdiff_t
tlsOffset
=
0
;
static
thread_key_t
tlsKey
;
void
ThreadLocalStorage
::
pd_invalidate_all
()
{}
// nothing to do
typedef
int
(
*
TSSA_Entry
)
(
ptrdiff_t
*
,
int
,
int
)
;
typedef
ptrdiff_t
(
*
TSO_Entry
)
(
int
)
;
bool
ThreadLocalStorage
::
_initialized
=
false
;
ThreadLocalStorage
::
pd_tlsAccessMode
ThreadLocalStorage
::
pd_getTlsAccessMode
()
{
guarantee
(
tlsMode
!=
pd_tlsAccessUndefined
,
"tlsMode not set"
)
;
return
tlsMode
;
void
ThreadLocalStorage
::
init
()
{
_initialized
=
true
;
}
ptrdiff_t
ThreadLocalStorage
::
pd_getTlsOffset
()
{
guarantee
(
tlsMode
!=
pd_tlsAccessUndefined
,
"tlsMode not set"
)
;
return
tlsOffset
;
bool
ThreadLocalStorage
::
is_initialized
()
{
return
_initialized
;
}
// TODO: Consider the following improvements:
//
// 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
()
;
Thread
*
ThreadLocalStorage
::
get_thread_slow
()
{
return
thread
();
}
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
()
{
return
ThreadLocalStorage
::
thread
();
}
src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp
浏览文件 @
3279e351
/*
* Copyright (c) 1998, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
5
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -25,61 +25,15 @@
#ifndef 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
:
static
Thread
*
_get_thread_cache
[];
// index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size]
static
Thread
*
get_thread_via_cache_slowly
(
uintptr_t
raw_id
,
int
index
);
static
__thread
Thread
*
_thr_current
;
NOT_PRODUCT
(
static
int
_tcacheHit
;)
NOT_PRODUCT
(
static
int
_tcacheMiss
;)
static
bool
_initialized
;
// needed for shared API
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
();
#endif // OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
src/share/vm/runtime/threadLocalStorage.cpp
浏览文件 @
3279e351
/*
* Copyright (c) 1997, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
5
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -38,6 +38,11 @@
# include "os_bsd.inline.hpp"
#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
int
ThreadLocalStorage
::
_thread_index
=
-
1
;
...
...
@@ -65,3 +70,5 @@ void ThreadLocalStorage::init() {
bool
ThreadLocalStorage
::
is_initialized
()
{
return
(
thread_index
()
!=
-
1
);
}
#endif // SOLARIS
src/share/vm/runtime/threadLocalStorage.hpp
浏览文件 @
3279e351
...
...
@@ -38,10 +38,14 @@ extern "C" Thread* get_thread();
extern
"C"
uintptr_t
_raw_thread_id
();
class
ThreadLocalStorage
:
AllStatic
{
// Exported API
public:
static
void
set_thread
(
Thread
*
thread
);
static
Thread
*
get_thread_slow
();
static
void
invalidate_all
()
{
pd_invalidate_all
();
}
static
void
init
();
static
bool
is_initialized
();
// Machine dependent stuff
#ifdef TARGET_OS_ARCH_linux_x86
...
...
@@ -78,17 +82,12 @@ class ThreadLocalStorage : AllStatic {
# include "threadLS_bsd_zero.hpp"
#endif
#ifndef SOLARIS
public:
// Accessor
static
inline
int
thread_index
()
{
return
_thread_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:
static
int
_thread_index
;
...
...
@@ -97,6 +96,9 @@ class ThreadLocalStorage : AllStatic {
// Processor dependent parts of set_thread and initialization
static
void
pd_set_thread
(
Thread
*
thread
);
static
void
pd_init
();
#endif // SOLARIS
// Invalidate any thread cacheing or optimization schemes.
static
void
pd_invalidate_all
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录