summaryrefslogtreecommitdiffstats
path: root/runtime/thread.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/thread.cc')
-rw-r--r--runtime/thread.cc102
1 files changed, 7 insertions, 95 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc
index a9173d5..6e8f89c 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -96,11 +96,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
void Thread::InitTlsEntryPoints() {
// Insert a placeholder so we can easily tell if we call an unimplemented entry point.
- uintptr_t* begin = reinterpret_cast<uintptr_t*>(&tlsPtr_.quick_entrypoints);
- uintptr_t* end = reinterpret_cast<uintptr_t*>(
- reinterpret_cast<uint8_t*>(&tlsPtr_.interpreter_entrypoints) +
- sizeof(tlsPtr_.interpreter_entrypoints));
- DCHECK_LT(begin, end);
+ uintptr_t* begin = reinterpret_cast<uintptr_t*>(&tlsPtr_.interpreter_entrypoints);
+ uintptr_t* end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(&tlsPtr_.quick_entrypoints) +
+ sizeof(tlsPtr_.quick_entrypoints));
for (uintptr_t* it = begin; it != end; ++it) {
*it = reinterpret_cast<uintptr_t>(UnimplementedEntryPoint);
}
@@ -108,90 +106,7 @@ void Thread::InitTlsEntryPoints() {
&tlsPtr_.quick_entrypoints);
}
-static constexpr bool kUseWriteProtectScheme = true;
-
-static size_t GetProtectionOffset() {
- return RoundUp(QUICK_ENTRYPOINT_OFFSET(sizeof(void*), pInstanceofNonTrivial).Uint32Value(), 16);
-}
-
-// Allocate a thread. This might do some magic to use two pages.
-Thread* Thread::AllocateThread(bool is_daemon) {
- if (!kUseWriteProtectScheme) {
- return new Thread(is_daemon);
- }
-
- std::string error_msg;
- MemMap* mem_map = MemMap::MapAnonymous("some thread",
- nullptr,
- 2 * kPageSize,
- PROT_READ | PROT_WRITE,
- false,
- false,
- &error_msg);
- if (mem_map == nullptr) {
- PLOG(FATAL) << error_msg;
- }
-
- uint8_t* second_page_address = mem_map->Begin() + kPageSize;
- const uint32_t offset = GetProtectionOffset();
- uintptr_t start_address = reinterpret_cast<uintptr_t>(second_page_address) - offset;
- DCHECK_GE(start_address, reinterpret_cast<uintptr_t>(mem_map->Begin()) + sizeof(void*));
- void* start_address_ptr = reinterpret_cast<void*>(start_address);
- Thread* t = new (start_address_ptr) Thread(is_daemon);
-
- // Store a pointer to the MemMap at the bottom.
- *reinterpret_cast<MemMap**>(mem_map->Begin()) = mem_map;
-
- return t;
-}
-
-static void ProtectThread(Thread* thread) {
- if (!kUseWriteProtectScheme) {
- return;
- }
-
- uintptr_t thread_addr = reinterpret_cast<uintptr_t>(thread);
- DCHECK_EQ(RoundUp(thread_addr, kPageSize), thread_addr + GetProtectionOffset());
- void* page_address = reinterpret_cast<void*>(RoundUp(thread_addr, kPageSize));
- mprotect(page_address, kPageSize, PROT_READ);
-}
-
-static void UnprotectThread(Thread* thread) {
- if (!kUseWriteProtectScheme) {
- return;
- }
-
- uintptr_t thread_addr = reinterpret_cast<uintptr_t>(thread);
- DCHECK_EQ(RoundUp(thread_addr, kPageSize), thread_addr + GetProtectionOffset());
- void* page_address = reinterpret_cast<void*>(RoundUp(thread_addr, kPageSize));
- mprotect(page_address, kPageSize, PROT_READ | PROT_WRITE);
-}
-
-void Thread::DeleteThread(Thread* thread) {
- if (!kUseWriteProtectScheme) {
- delete thread;
- return;
- }
-
- if (thread == nullptr) {
- return;
- }
-
- UnprotectThread(thread);
- thread->~Thread();
-
- // There should be the MemMap* at the bottom.
- MemMap* mem_map =
- *reinterpret_cast<MemMap**>(RoundDown(reinterpret_cast<uintptr_t>(thread), kPageSize));
-
- delete mem_map;
-}
-
void Thread::InitStringEntryPoints() {
- // Ensure things are writable. This may be a late initialization of the entrypoints for the main
- // thread.
- UnprotectThread(this);
-
ScopedObjectAccess soa(this);
QuickEntryPoints* qpoints = &tlsPtr_.quick_entrypoints;
qpoints->pNewEmptyString = reinterpret_cast<void(*)()>(
@@ -226,9 +141,6 @@ void Thread::InitStringEntryPoints() {
soa.DecodeMethod(WellKnownClasses::java_lang_StringFactory_newStringFromStringBuffer));
qpoints->pNewStringFromStringBuilder = reinterpret_cast<void(*)()>(
soa.DecodeMethod(WellKnownClasses::java_lang_StringFactory_newStringFromStringBuilder));
-
- // This is a good time to protect things, now that all entrypoints are set.
- ProtectThread(this);
}
void Thread::ResetQuickAllocEntryPointsForThread() {
@@ -494,7 +406,7 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz
return;
}
- Thread* child_thread = AllocateThread(is_daemon);
+ Thread* child_thread = new Thread(is_daemon);
// Use global JNI ref to hold peer live while child thread starts.
child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);
stack_size = FixStackSize(stack_size);
@@ -542,7 +454,7 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz
// Manually delete the global reference since Thread::Init will not have been run.
env->DeleteGlobalRef(child_thread->tlsPtr_.jpeer);
child_thread->tlsPtr_.jpeer = nullptr;
- DeleteThread(child_thread);
+ delete child_thread;
child_thread = nullptr;
// TODO: remove from thread group?
env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
@@ -613,11 +525,11 @@ Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_g
return nullptr;
} else {
Runtime::Current()->StartThreadBirth();
- self = AllocateThread(as_daemon);
+ self = new Thread(as_daemon);
bool init_success = self->Init(runtime->GetThreadList(), runtime->GetJavaVM());
Runtime::Current()->EndThreadBirth();
if (!init_success) {
- DeleteThread(self);
+ delete self;
return nullptr;
}
}