blob: abd45db5a27278bbf5e290ff2c97f24f17d55b92 [file] [log] [blame]
Carl Shapirob5573532011-07-12 18:22:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "src/thread.h"
4
5#include <algorithm>
6#include <list>
7#include <errno.h>
8#include <pthread.h>
9
10#include "src/runtime.h"
11
12namespace art {
13
14pthread_key_t Thread::pthread_key_self_;
15
16Mutex* Mutex::Create(const char* name) {
17 Mutex* mu = new Mutex(name);
18 int result = pthread_mutex_init(&mu->lock_impl_, NULL);
19 CHECK(result == 0);
20 return mu;
21}
22
23void Mutex::Lock() {
24 int result = pthread_mutex_lock(&lock_impl_);
25 CHECK_EQ(result, 0);
26 SetOwner(Thread::Current());
27}
28
29bool Mutex::TryLock() {
30 int result = pthread_mutex_lock(&lock_impl_);
31 if (result == EBUSY) {
32 return false;
33 } else {
34 CHECK_EQ(result, 0);
35 SetOwner(Thread::Current());
36 return true;
37 }
38}
39
40void Mutex::Unlock() {
41 CHECK(GetOwner() == Thread::Current());
42 int result = pthread_mutex_unlock(&lock_impl_);
43 CHECK_EQ(result, 0);
44 SetOwner(Thread::Current());
45}
46
47Thread* Thread::Create(const char* name) {
48 LOG(FATAL) << "Unimplemented";
49 return NULL;
50}
51
52static void ThreadExitCheck(void* arg) {
53 LG << "Thread exit check";
54}
55
56bool Thread::Init() {
57 // Allocate a TLS slot.
58 if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
59 LOG(WARN) << "pthread_key_create failed";
60 return false;
61 }
62
63 // Double-check the TLS slot allocation.
64 if (pthread_getspecific(pthread_key_self_) != NULL) {
65 LOG(WARN) << "newly-created pthread TLS slot is not NULL";
66 return false;
67 }
68
69 // TODO: initialize other locks and condition variables
70
71 return true;
72}
73
74ThreadList::ThreadList() {
75 lock_ = Mutex::Create("ThreadList::Lock");
76}
77
78ThreadList::~ThreadList() {
79 // Make sure that all threads have exited and unregistered when we
80 // reach this point. This means that all daemon threads had been
81 // shutdown cleanly.
82 CHECK_EQ(list_.size(), 0);
83 delete lock_;
84 lock_ = NULL;
85}
86
87void ThreadList::Register(Thread* thread) {
88 MutexLock mu(lock_);
89 CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
90 list_.push_front(thread);
91}
92
93void ThreadList::Unregister(Thread* thread) {
94 MutexLock mu(lock_);
95 CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
96 list_.remove(thread);
97}
98
99void ThreadList::Init(Runtime* runtime) {
100 ThreadList* thread_list = new ThreadList();
101 runtime->SetThreadList(thread_list);
102}
103
104} // namespace