thread.cc revision a5780dad67556297c8ca5f2608c53b193e6c4514
1// Copyright 2011 Google Inc. All Rights Reserved. 2 3#include "src/thread.h" 4 5#include <algorithm> 6#include <cerrno> 7#include <list> 8#include <pthread.h> 9#include <sys/mman.h> 10 11#include "src/runtime.h" 12#include "src/utils.h" 13 14namespace art { 15 16pthread_key_t Thread::pthread_key_self_; 17 18Mutex* Mutex::Create(const char* name) { 19 Mutex* mu = new Mutex(name); 20 int result = pthread_mutex_init(&mu->lock_impl_, NULL); 21 CHECK(result == 0); 22 return mu; 23} 24 25void Mutex::Lock() { 26 int result = pthread_mutex_lock(&lock_impl_); 27 CHECK_EQ(result, 0); 28 SetOwner(Thread::Current()); 29} 30 31bool Mutex::TryLock() { 32 int result = pthread_mutex_lock(&lock_impl_); 33 if (result == EBUSY) { 34 return false; 35 } else { 36 CHECK_EQ(result, 0); 37 SetOwner(Thread::Current()); 38 return true; 39 } 40} 41 42void Mutex::Unlock() { 43 CHECK(GetOwner() == Thread::Current()); 44 int result = pthread_mutex_unlock(&lock_impl_); 45 CHECK_EQ(result, 0); 46 SetOwner(Thread::Current()); 47} 48 49void* ThreadStart(void *arg) { 50 LOG(FATAL) << "Unimplemented"; 51 return NULL; 52} 53 54Thread* Thread::Create(size_t stack_size) { 55 int prot = PROT_READ | PROT_WRITE; 56 // TODO: require the stack size to be page aligned? 57 size_t length = RoundUp(stack_size, 0x1000); 58 void* stack_limit = mmap(NULL, length, prot, MAP_PRIVATE, -1, 0); 59 if (stack_limit == MAP_FAILED) { 60 LOG(FATAL) << "mmap"; 61 return false; 62 } 63 64 Thread* new_thread = new Thread; 65 new_thread->stack_limit_ = static_cast<byte*>(stack_limit); 66 new_thread->stack_base_ = new_thread->stack_limit_ + length; 67 68 pthread_attr_t attr; 69 int result = pthread_attr_init(&attr); 70 CHECK_EQ(result, 0); 71 72 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 73 CHECK_EQ(result, 0); 74 75 pthread_t handle; 76 result = pthread_create(&handle, &attr, ThreadStart, new_thread); 77 CHECK_EQ(result, 0); 78 79 result = pthread_attr_destroy(&attr); 80 CHECK_EQ(result, 0); 81 82 return new_thread; 83} 84 85Thread* Thread::Attach() { 86 Thread* thread = new Thread; 87 88 thread->stack_limit_ = reinterpret_cast<byte*>(-1); // TODO: getrlimit 89 uintptr_t addr = reinterpret_cast<uintptr_t>(&thread); // TODO: ask pthreads 90 uintptr_t stack_base = RoundUp(addr, 4096); 91 thread->stack_base_ = reinterpret_cast<byte*>(stack_base); 92 // TODO: set the stack size 93 94 thread->handle_ = pthread_self(); 95 96 thread->state_ = kRunnable; 97 98 errno = pthread_setspecific(Thread::pthread_key_self_, thread); 99 if (errno != 0) { 100 PLOG(FATAL) << "pthread_setspecific failed"; 101 } 102 103 return thread; 104} 105 106static void ThreadExitCheck(void* arg) { 107 LG << "Thread exit check"; 108} 109 110bool Thread::Init() { 111 // Allocate a TLS slot. 112 if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) { 113 PLOG(WARNING) << "pthread_key_create failed"; 114 return false; 115 } 116 117 // Double-check the TLS slot allocation. 118 if (pthread_getspecific(pthread_key_self_) != NULL) { 119 LOG(WARNING) << "newly-created pthread TLS slot is not NULL"; 120 return false; 121 } 122 123 // TODO: initialize other locks and condition variables 124 125 return true; 126} 127 128ThreadList* ThreadList::Create() { 129 return new ThreadList; 130} 131 132ThreadList::ThreadList() { 133 lock_ = Mutex::Create("ThreadList::Lock"); 134} 135 136ThreadList::~ThreadList() { 137 // Make sure that all threads have exited and unregistered when we 138 // reach this point. This means that all daemon threads had been 139 // shutdown cleanly. 140 CHECK_EQ(list_.size(), 0); 141 delete lock_; 142 lock_ = NULL; 143} 144 145void ThreadList::Register(Thread* thread) { 146 MutexLock mu(lock_); 147 CHECK(find(list_.begin(), list_.end(), thread) == list_.end()); 148 list_.push_front(thread); 149} 150 151void ThreadList::Unregister(Thread* thread) { 152 MutexLock mu(lock_); 153 CHECK(find(list_.begin(), list_.end(), thread) != list_.end()); 154 list_.remove(thread); 155} 156 157} // namespace 158