Chromium Code Reviews| 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 #ifndef VM_LOCKERS_H_ | 5 #ifndef VM_LOCKERS_H_ |
| 6 #define VM_LOCKERS_H_ | 6 #define VM_LOCKERS_H_ |
| 7 | 7 |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/allocation.h" | 9 #include "vm/allocation.h" |
| 10 #include "vm/globals.h" | 10 #include "vm/globals.h" |
| 11 #include "vm/isolate.h" | 11 #include "vm/isolate.h" |
| 12 #include "vm/os_thread.h" | 12 #include "vm/os_thread.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 /* | |
| 17 * Normal mutex locker : | |
| 18 * This locker abstraction should only be used when the enclosing code will | |
|
srdjan
2016/03/01 16:46:23
s/will not/cannot/
siva
2016/03/01 18:59:54
Done.
| |
| 19 * not trigger a safepoint. In debug mode this class increments the | |
| 20 * no_safepoint_scope_depth variable for the current thread when the lock is | |
| 21 * taken and decrements it when the lock is released. NOTE: please do not use | |
| 22 * the passed in mutex object independent of the locker class, For example the | |
| 23 * code below will not assert correctly: | |
| 24 * { | |
| 25 * MutexLocker ml(m); | |
| 26 * .... | |
| 27 * m->Exit(); | |
| 28 * .... | |
| 29 * m->Enter(); | |
|
Cutch
2016/03/01 15:08:07
Why don't we make the Enter and Exit on the Mutex/
siva
2016/03/01 18:59:53
I tried this but there are a number of places wher
| |
| 30 * ... | |
| 31 * } | |
| 32 * Always use the locker object even when the lock needs to be released | |
| 33 * temporarily, e.g: | |
| 34 * { | |
| 35 * MutexLocker ml(m); | |
| 36 * .... | |
| 37 * ml.Exit(); | |
| 38 * .... | |
| 39 * ml.Enter(); | |
| 40 * ... | |
| 41 * } | |
| 42 */ | |
| 16 class MutexLocker : public ValueObject { | 43 class MutexLocker : public ValueObject { |
| 17 public: | 44 public: |
| 18 explicit MutexLocker(Mutex* mutex) : mutex_(mutex) { | 45 explicit MutexLocker(Mutex* mutex, bool no_safepoint_scope = true) |
|
Cutch
2016/03/01 15:08:07
Can we use an enum rather than a boolean as the se
siva
2016/03/01 18:59:54
An enum here seems like an overkill, we want the n
| |
| 46 : mutex_(mutex), no_safepoint_scope_(no_safepoint_scope) { | |
| 19 ASSERT(mutex != NULL); | 47 ASSERT(mutex != NULL); |
| 20 // TODO(iposva): Consider adding a no GC scope here. | 48 #if defined(DEBUG) |
| 49 if (no_safepoint_scope_) { | |
| 50 Thread* thread = Thread::Current(); | |
| 51 if (thread != NULL) { | |
| 52 thread->IncrementNoSafepointScopeDepth(); | |
| 53 } else { | |
| 54 no_safepoint_scope_ = false; | |
| 55 } | |
| 56 } | |
| 57 #endif | |
| 21 mutex_->Lock(); | 58 mutex_->Lock(); |
| 22 } | 59 } |
| 23 | 60 |
| 24 virtual ~MutexLocker() { | 61 virtual ~MutexLocker() { |
| 25 mutex_->Unlock(); | 62 mutex_->Unlock(); |
| 26 // TODO(iposva): Consider decrementing the no GC scope here. | 63 #if defined(DEBUG) |
| 64 if (no_safepoint_scope_) { | |
| 65 Thread::Current()->DecrementNoSafepointScopeDepth(); | |
| 66 } | |
| 67 #endif | |
| 68 } | |
| 69 | |
| 70 void Lock() const { | |
| 71 #if defined(DEBUG) | |
| 72 if (no_safepoint_scope_) { | |
| 73 Thread::Current()->IncrementNoSafepointScopeDepth(); | |
| 74 } | |
| 75 #endif | |
| 76 mutex_->Lock(); | |
| 77 } | |
| 78 void Unlock() const { | |
| 79 mutex_->Unlock(); | |
| 80 #if defined(DEBUG) | |
| 81 if (no_safepoint_scope_) { | |
| 82 Thread::Current()->DecrementNoSafepointScopeDepth(); | |
| 83 } | |
| 84 #endif | |
| 27 } | 85 } |
| 28 | 86 |
| 29 private: | 87 private: |
| 30 Mutex* const mutex_; | 88 Mutex* const mutex_; |
| 89 bool no_safepoint_scope_; | |
| 31 | 90 |
| 32 DISALLOW_COPY_AND_ASSIGN(MutexLocker); | 91 DISALLOW_COPY_AND_ASSIGN(MutexLocker); |
| 33 }; | 92 }; |
| 34 | 93 |
| 35 | 94 /* |
| 95 * Normal monitor locker : | |
| 96 * This locker abstraction should only be used when the enclosing code will | |
|
srdjan
2016/03/01 16:46:23
ditto?
siva
2016/03/01 18:59:53
Done.
| |
| 97 * not trigger a safepoint. In debug mode this class increments the | |
| 98 * no_safepoint_scope_depth variable for the current thread when the lock is | |
| 99 * taken and decrements it when the lock is released. NOTE: please do not use | |
| 100 * the passed in mutex object independent of the locker class, For example the | |
| 101 * code below will not assert correctly: | |
| 102 * { | |
| 103 * MonitorLocker ml(m); | |
| 104 * .... | |
| 105 * m->Exit(); | |
| 106 * .... | |
| 107 * m->Enter(); | |
| 108 * ... | |
| 109 * } | |
| 110 * Always use the locker object even when the lock needs to be released | |
| 111 * temporarily, e.g: | |
| 112 * { | |
| 113 * MonitorLocker ml(m); | |
| 114 * .... | |
| 115 * ml.Exit(); | |
| 116 * .... | |
| 117 * ml.Enter(); | |
| 118 * ... | |
| 119 * } | |
| 120 */ | |
| 36 class MonitorLocker : public ValueObject { | 121 class MonitorLocker : public ValueObject { |
| 37 public: | 122 public: |
| 38 explicit MonitorLocker(Monitor* monitor) : monitor_(monitor) { | 123 explicit MonitorLocker(Monitor* monitor, bool no_safepoint_scope = true) |
| 124 : monitor_(monitor), no_safepoint_scope_(no_safepoint_scope) { | |
| 39 ASSERT(monitor != NULL); | 125 ASSERT(monitor != NULL); |
| 40 // TODO(iposva): Consider adding a no GC scope here. | 126 #if defined(DEBUG) |
| 127 if (no_safepoint_scope_) { | |
| 128 Thread* thread = Thread::Current(); | |
| 129 if (thread != NULL) { | |
| 130 thread->IncrementNoSafepointScopeDepth(); | |
| 131 } else { | |
| 132 no_safepoint_scope_ = false; | |
| 133 } | |
| 134 } | |
| 135 #endif | |
| 41 monitor_->Enter(); | 136 monitor_->Enter(); |
| 42 } | 137 } |
| 43 | 138 |
| 44 virtual ~MonitorLocker() { | 139 virtual ~MonitorLocker() { |
| 45 monitor_->Exit(); | 140 monitor_->Exit(); |
| 46 // TODO(iposva): Consider decrementing the no GC scope here. | 141 #if defined(DEBUG) |
|
Cutch
2016/03/01 15:08:07
here and elsewhere:
DEBUG_ONLY(
)
siva
2016/03/01 18:59:54
I looked at uses of DEBUG_ONLY and looks like the
| |
| 142 if (no_safepoint_scope_) { | |
| 143 Thread::Current()->DecrementNoSafepointScopeDepth(); | |
| 144 } | |
| 145 #endif | |
| 146 } | |
| 147 | |
| 148 void Enter() const { | |
| 149 #if defined(DEBUG) | |
| 150 if (no_safepoint_scope_) { | |
| 151 Thread::Current()->IncrementNoSafepointScopeDepth(); | |
| 152 } | |
| 153 #endif | |
| 154 monitor_->Enter(); | |
| 155 } | |
| 156 void Exit() const { | |
| 157 monitor_->Exit(); | |
| 158 #if defined(DEBUG) | |
| 159 if (no_safepoint_scope_) { | |
| 160 Thread::Current()->DecrementNoSafepointScopeDepth(); | |
| 161 } | |
| 162 #endif | |
| 47 } | 163 } |
| 48 | 164 |
| 49 Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout) { | 165 Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout) { |
| 50 return monitor_->Wait(millis); | 166 return monitor_->Wait(millis); |
| 51 } | 167 } |
| 52 | 168 |
| 53 Monitor::WaitResult WaitWithSafepointCheck( | 169 Monitor::WaitResult WaitWithSafepointCheck( |
| 54 Thread* thread, int64_t millis = Monitor::kNoTimeout); | 170 Thread* thread, int64_t millis = Monitor::kNoTimeout); |
| 55 | 171 |
| 56 Monitor::WaitResult WaitMicros(int64_t micros = Monitor::kNoTimeout) { | 172 Monitor::WaitResult WaitMicros(int64_t micros = Monitor::kNoTimeout) { |
| 57 return monitor_->WaitMicros(micros); | 173 return monitor_->WaitMicros(micros); |
| 58 } | 174 } |
| 59 | 175 |
| 60 void Notify() { | 176 void Notify() { |
| 61 monitor_->Notify(); | 177 monitor_->Notify(); |
| 62 } | 178 } |
| 63 | 179 |
| 64 void NotifyAll() { | 180 void NotifyAll() { |
| 65 monitor_->NotifyAll(); | 181 monitor_->NotifyAll(); |
| 66 } | 182 } |
| 67 | 183 |
| 68 private: | 184 private: |
| 69 Monitor* const monitor_; | 185 Monitor* const monitor_; |
| 186 bool no_safepoint_scope_; | |
| 70 | 187 |
| 71 DISALLOW_COPY_AND_ASSIGN(MonitorLocker); | 188 DISALLOW_COPY_AND_ASSIGN(MonitorLocker); |
| 72 }; | 189 }; |
| 73 | 190 |
| 74 | 191 /* |
| 75 // SafepointMutexLocker objects are used in code where the locks are | 192 * Safepoint mutex locker : |
| 76 // more coarse grained and a safepoint operation could be potentially | 193 * This locker abstraction should be used when the lock is more coarse |
|
Cutch
2016/03/01 15:08:07
I don't see why the granularity of the lock matter
siva
2016/03/01 18:59:53
Changed the comment to remove the coarse wording.
| |
| 77 // triggered while holding this lock. This ensures that other threads | 194 * grained and the enclosing code could potentially trigger a safepoint. |
| 78 // which try to acquire the same lock will be marked as being at a | 195 * This locker ensures that other threads that try to acquire the same lock |
| 79 // safepoint when they are blocked. | 196 * will be marked as being at a safepoint if they get blocked trying to |
| 197 * acquire the lock. | |
| 198 * NOTE: please do not use the passed in mutex object independent of the locker | |
| 199 * class, For example the code below will not work correctly: | |
| 200 * { | |
| 201 * SafepointMutexLocker ml(m); | |
| 202 * .... | |
| 203 * m->Exit(); | |
| 204 * .... | |
| 205 * m->Enter(); | |
| 206 * ... | |
| 207 * } | |
| 208 */ | |
| 80 class SafepointMutexLocker : public ValueObject { | 209 class SafepointMutexLocker : public ValueObject { |
| 81 public: | 210 public: |
| 82 explicit SafepointMutexLocker(Mutex* mutex); | 211 explicit SafepointMutexLocker(Mutex* mutex); |
| 83 virtual ~SafepointMutexLocker() { | 212 virtual ~SafepointMutexLocker() { |
| 84 mutex_->Unlock(); | 213 mutex_->Unlock(); |
| 85 } | 214 } |
| 86 | 215 |
| 87 private: | 216 private: |
| 88 Mutex* const mutex_; | 217 Mutex* const mutex_; |
| 89 | 218 |
| 90 DISALLOW_COPY_AND_ASSIGN(SafepointMutexLocker); | 219 DISALLOW_COPY_AND_ASSIGN(SafepointMutexLocker); |
| 91 }; | 220 }; |
| 92 | 221 |
| 222 /* | |
| 223 * Safepoint monitor locker : | |
| 224 * This locker abstraction should be used when the lock is more coarse | |
| 225 * grained and the enclosing code could potentially trigger a safepoint. | |
| 226 * This locker ensures that other threads that try to acquire the same lock | |
| 227 * will be marked as being at a safepoint if they get blocked trying to | |
| 228 * acquire the lock. | |
| 229 * NOTE: please do not use the passed in monitor object independent of the locke r | |
|
Cutch
2016/03/01 15:08:07
line length
siva
2016/03/01 18:59:53
Done.
| |
| 230 * class, For example the code below will not work correctly: | |
| 231 * { | |
| 232 * SafepointMonitorLocker ml(m); | |
| 233 * .... | |
| 234 * m->Exit(); | |
| 235 * .... | |
| 236 * m->Enter(); | |
| 237 * ... | |
| 238 * } | |
| 239 */ | |
| 240 class SafepointMonitorLocker : public ValueObject { | |
| 241 public: | |
| 242 explicit SafepointMonitorLocker(Monitor* monitor); | |
| 243 virtual ~SafepointMonitorLocker() { | |
| 244 monitor_->Exit(); | |
| 245 } | |
| 246 | |
| 247 Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout); | |
| 248 | |
| 249 private: | |
| 250 Monitor* const monitor_; | |
| 251 | |
| 252 DISALLOW_COPY_AND_ASSIGN(SafepointMonitorLocker); | |
| 253 }; | |
| 254 | |
| 93 } // namespace dart | 255 } // namespace dart |
| 94 | 256 |
| 95 | 257 |
| 96 #endif // VM_LOCKERS_H_ | 258 #endif // VM_LOCKERS_H_ |
| OLD | NEW |