| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <errno.h> | 5 #include <errno.h> |
| 6 #include <sys/time.h> | 6 #include <sys/time.h> |
| 7 | 7 |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/thread.h" | 9 #include "vm/thread.h" |
| 10 | 10 |
| 11 namespace dart { | 11 namespace dart { |
| 12 | 12 |
| 13 #define VALIDATE_PTHREAD_RESULT(result) \ | 13 #define VALIDATE_PTHREAD_RESULT(result) \ |
| 14 if (result != 0) { \ | 14 if (result != 0) { \ |
| 15 FATAL2("pthread error: %d (%s)", result, strerror(result)); \ | 15 FATAL2("pthread error: %d (%s)", result, strerror(result)); \ |
| 16 } | 16 } |
| 17 | 17 |
| 18 | 18 |
| 19 static void ComputeTimeSpec(struct timespec* ts, int64_t millis) { | |
| 20 int64_t secs = millis / kMillisecondsPerSecond; | |
| 21 int64_t nanos = | |
| 22 (millis - (secs * kMillisecondsPerSecond)) * kNanosecondsPerMillisecond; | |
| 23 int result = clock_gettime(CLOCK_MONOTONIC, ts); | |
| 24 ASSERT(result == 0); | |
| 25 ts->tv_sec += secs; | |
| 26 ts->tv_nsec += nanos; | |
| 27 if (ts->tv_nsec >= kNanosecondsPerSecond) { | |
| 28 ts->tv_sec += 1; | |
| 29 ts->tv_nsec -= kNanosecondsPerSecond; | |
| 30 } | |
| 31 } | |
| 32 | |
| 33 | |
| 34 class ThreadStartData { | 19 class ThreadStartData { |
| 35 public: | 20 public: |
| 36 ThreadStartData(Thread::ThreadStartFunction function, | 21 ThreadStartData(Thread::ThreadStartFunction function, |
| 37 uword parameter, | 22 uword parameter, |
| 38 Thread* thread) | 23 Thread* thread) |
| 39 : function_(function), parameter_(parameter), thread_(thread) {} | 24 : function_(function), parameter_(parameter), thread_(thread) {} |
| 40 | 25 |
| 41 Thread::ThreadStartFunction function() const { return function_; } | 26 Thread::ThreadStartFunction function() const { return function_; } |
| 42 uword parameter() const { return parameter_; } | 27 uword parameter() const { return parameter_; } |
| 43 Thread* thread() const { return thread_; } | 28 Thread* thread() const { return thread_; } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 data_.tid_ = tid; | 80 data_.tid_ = tid; |
| 96 | 81 |
| 97 result = pthread_attr_destroy(&attr); | 82 result = pthread_attr_destroy(&attr); |
| 98 VALIDATE_PTHREAD_RESULT(result); | 83 VALIDATE_PTHREAD_RESULT(result); |
| 99 } | 84 } |
| 100 | 85 |
| 101 | 86 |
| 102 Thread::~Thread() { | 87 Thread::~Thread() { |
| 103 } | 88 } |
| 104 | 89 |
| 105 | |
| 106 Mutex::Mutex() { | |
| 107 pthread_mutexattr_t attr; | |
| 108 int result = pthread_mutexattr_init(&attr); | |
| 109 VALIDATE_PTHREAD_RESULT(result); | |
| 110 | |
| 111 #if defined(DEBUG) | |
| 112 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); | |
| 113 VALIDATE_PTHREAD_RESULT(result); | |
| 114 #endif // defined(DEBUG) | |
| 115 | |
| 116 result = pthread_mutex_init(data_.mutex(), &attr); | |
| 117 // Verify that creating a pthread_mutex succeeded. | |
| 118 VALIDATE_PTHREAD_RESULT(result); | |
| 119 | |
| 120 result = pthread_mutexattr_destroy(&attr); | |
| 121 VALIDATE_PTHREAD_RESULT(result); | |
| 122 } | |
| 123 | |
| 124 | |
| 125 Mutex::~Mutex() { | |
| 126 int result = pthread_mutex_destroy(data_.mutex()); | |
| 127 // Verify that the pthread_mutex was destroyed. | |
| 128 VALIDATE_PTHREAD_RESULT(result); | |
| 129 } | |
| 130 | |
| 131 | |
| 132 void Mutex::Lock() { | |
| 133 int result = pthread_mutex_lock(data_.mutex()); | |
| 134 // Specifically check for dead lock to help debugging. | |
| 135 ASSERT(result != EDEADLK); | |
| 136 ASSERT(result == 0); // Verify no other errors. | |
| 137 // TODO(iposva): Do we need to track lock owners? | |
| 138 } | |
| 139 | |
| 140 | |
| 141 bool Mutex::TryLock() { | |
| 142 int result = pthread_mutex_trylock(data_.mutex()); | |
| 143 // Return false if the lock is busy and locking failed. | |
| 144 if (result == EBUSY) { | |
| 145 return false; | |
| 146 } | |
| 147 ASSERT(result == 0); // Verify no other errors. | |
| 148 // TODO(iposva): Do we need to track lock owners? | |
| 149 return true; | |
| 150 } | |
| 151 | |
| 152 | |
| 153 void Mutex::Unlock() { | |
| 154 // TODO(iposva): Do we need to track lock owners? | |
| 155 int result = pthread_mutex_unlock(data_.mutex()); | |
| 156 // Specifically check for wrong thread unlocking to aid debugging. | |
| 157 ASSERT(result != EPERM); | |
| 158 ASSERT(result == 0); // Verify no other errors. | |
| 159 } | |
| 160 | |
| 161 | |
| 162 Monitor::Monitor() { | |
| 163 pthread_mutexattr_t mutex_attr; | |
| 164 int result = pthread_mutexattr_init(&mutex_attr); | |
| 165 VALIDATE_PTHREAD_RESULT(result); | |
| 166 | |
| 167 #if defined(DEBUG) | |
| 168 result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); | |
| 169 VALIDATE_PTHREAD_RESULT(result); | |
| 170 #endif // defined(DEBUG) | |
| 171 | |
| 172 result = pthread_mutex_init(data_.mutex(), &mutex_attr); | |
| 173 VALIDATE_PTHREAD_RESULT(result); | |
| 174 | |
| 175 result = pthread_mutexattr_destroy(&mutex_attr); | |
| 176 VALIDATE_PTHREAD_RESULT(result); | |
| 177 | |
| 178 pthread_condattr_t cond_attr; | |
| 179 result = pthread_condattr_init(&cond_attr); | |
| 180 VALIDATE_PTHREAD_RESULT(result); | |
| 181 | |
| 182 result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC); | |
| 183 VALIDATE_PTHREAD_RESULT(result); | |
| 184 | |
| 185 result = pthread_cond_init(data_.cond(), &cond_attr); | |
| 186 VALIDATE_PTHREAD_RESULT(result); | |
| 187 | |
| 188 result = pthread_condattr_destroy(&cond_attr); | |
| 189 VALIDATE_PTHREAD_RESULT(result); | |
| 190 } | |
| 191 | |
| 192 | |
| 193 Monitor::~Monitor() { | |
| 194 int result = pthread_mutex_destroy(data_.mutex()); | |
| 195 VALIDATE_PTHREAD_RESULT(result); | |
| 196 | |
| 197 result = pthread_cond_destroy(data_.cond()); | |
| 198 VALIDATE_PTHREAD_RESULT(result); | |
| 199 } | |
| 200 | |
| 201 | |
| 202 void Monitor::Enter() { | |
| 203 int result = pthread_mutex_lock(data_.mutex()); | |
| 204 VALIDATE_PTHREAD_RESULT(result); | |
| 205 // TODO(iposva): Do we need to track lock owners? | |
| 206 } | |
| 207 | |
| 208 | |
| 209 void Monitor::Exit() { | |
| 210 // TODO(iposva): Do we need to track lock owners? | |
| 211 int result = pthread_mutex_unlock(data_.mutex()); | |
| 212 VALIDATE_PTHREAD_RESULT(result); | |
| 213 } | |
| 214 | |
| 215 | |
| 216 Monitor::WaitResult Monitor::Wait(int64_t millis) { | |
| 217 // TODO(iposva): Do we need to track lock owners? | |
| 218 Monitor::WaitResult retval = kNotified; | |
| 219 if (millis == 0) { | |
| 220 // Wait forever. | |
| 221 int result = pthread_cond_wait(data_.cond(), data_.mutex()); | |
| 222 VALIDATE_PTHREAD_RESULT(result); | |
| 223 } else { | |
| 224 struct timespec ts; | |
| 225 ComputeTimeSpec(&ts, millis); | |
| 226 int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts); | |
| 227 ASSERT((result == 0) || (result == ETIMEDOUT)); | |
| 228 if (result == ETIMEDOUT) { | |
| 229 retval = kTimedOut; | |
| 230 } | |
| 231 } | |
| 232 return retval; | |
| 233 } | |
| 234 | |
| 235 | |
| 236 void Monitor::Notify() { | |
| 237 // TODO(iposva): Do we need to track lock owners? | |
| 238 int result = pthread_cond_signal(data_.cond()); | |
| 239 VALIDATE_PTHREAD_RESULT(result); | |
| 240 } | |
| 241 | |
| 242 | |
| 243 void Monitor::NotifyAll() { | |
| 244 // TODO(iposva): Do we need to track lock owners? | |
| 245 int result = pthread_cond_broadcast(data_.cond()); | |
| 246 VALIDATE_PTHREAD_RESULT(result); | |
| 247 } | |
| 248 | |
| 249 } // namespace dart | 90 } // namespace dart |
| OLD | NEW |