Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Unified Diff: runtime/vm/lockers.h

Issue 1748953003: - Add assertions in MutexLocker/MonitorLocker to ensure that the code enclosed (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review-comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/isolate.cc ('k') | runtime/vm/lockers.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/lockers.h
diff --git a/runtime/vm/lockers.h b/runtime/vm/lockers.h
index fd324f44811551673dd7a25f823abac28bac1b2e..a0b1a179be8f0aacce55c0d53b35777e442ee7b6 100644
--- a/runtime/vm/lockers.h
+++ b/runtime/vm/lockers.h
@@ -13,37 +13,156 @@
namespace dart {
+const bool kNoSafepointScope = true;
+const bool kDontAssertNoSafepointScope = false;
+
+/*
+ * Normal mutex locker :
+ * This locker abstraction should only be used when the enclosing code can
+ * not trigger a safepoint. In debug mode this class increments the
+ * no_safepoint_scope_depth variable for the current thread when the lock is
+ * taken and decrements it when the lock is released. NOTE: please do not use
+ * the passed in mutex object independent of the locker class, For example the
+ * code below will not assert correctly:
+ * {
+ * MutexLocker ml(m);
+ * ....
+ * m->Exit();
+ * ....
+ * m->Enter();
+ * ...
+ * }
+ * Always use the locker object even when the lock needs to be released
+ * temporarily, e.g:
+ * {
+ * MutexLocker ml(m);
+ * ....
+ * ml.Exit();
+ * ....
+ * ml.Enter();
+ * ...
+ * }
+ */
class MutexLocker : public ValueObject {
public:
- explicit MutexLocker(Mutex* mutex) : mutex_(mutex) {
+ explicit MutexLocker(Mutex* mutex, bool no_safepoint_scope = true)
+ : mutex_(mutex), no_safepoint_scope_(no_safepoint_scope) {
ASSERT(mutex != NULL);
- // TODO(iposva): Consider adding a no GC scope here.
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread* thread = Thread::Current();
+ if (thread != NULL) {
+ thread->IncrementNoSafepointScopeDepth();
+ } else {
+ no_safepoint_scope_ = false;
+ }
+ }
+#endif
mutex_->Lock();
}
virtual ~MutexLocker() {
mutex_->Unlock();
- // TODO(iposva): Consider decrementing the no GC scope here.
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread::Current()->DecrementNoSafepointScopeDepth();
+ }
+#endif
+ }
+
+ void Lock() const {
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread::Current()->IncrementNoSafepointScopeDepth();
+ }
+#endif
+ mutex_->Lock();
+ }
+ void Unlock() const {
+ mutex_->Unlock();
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread::Current()->DecrementNoSafepointScopeDepth();
+ }
+#endif
}
private:
Mutex* const mutex_;
+ bool no_safepoint_scope_;
DISALLOW_COPY_AND_ASSIGN(MutexLocker);
};
-
+/*
+ * Normal monitor locker :
+ * This locker abstraction should only be used when the enclosing code can
+ * not trigger a safepoint. In debug mode this class increments the
+ * no_safepoint_scope_depth variable for the current thread when the lock is
+ * taken and decrements it when the lock is released. NOTE: please do not use
+ * the passed in mutex object independent of the locker class, For example the
+ * code below will not assert correctly:
+ * {
+ * MonitorLocker ml(m);
+ * ....
+ * m->Exit();
+ * ....
+ * m->Enter();
+ * ...
+ * }
+ * Always use the locker object even when the lock needs to be released
+ * temporarily, e.g:
+ * {
+ * MonitorLocker ml(m);
+ * ....
+ * ml.Exit();
+ * ....
+ * ml.Enter();
+ * ...
+ * }
+ */
class MonitorLocker : public ValueObject {
public:
- explicit MonitorLocker(Monitor* monitor) : monitor_(monitor) {
+ explicit MonitorLocker(Monitor* monitor, bool no_safepoint_scope = true)
+ : monitor_(monitor), no_safepoint_scope_(no_safepoint_scope) {
ASSERT(monitor != NULL);
- // TODO(iposva): Consider adding a no GC scope here.
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread* thread = Thread::Current();
+ if (thread != NULL) {
+ thread->IncrementNoSafepointScopeDepth();
+ } else {
+ no_safepoint_scope_ = false;
+ }
+ }
+#endif
monitor_->Enter();
}
virtual ~MonitorLocker() {
monitor_->Exit();
- // TODO(iposva): Consider decrementing the no GC scope here.
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread::Current()->DecrementNoSafepointScopeDepth();
+ }
+#endif
+ }
+
+ void Enter() const {
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread::Current()->IncrementNoSafepointScopeDepth();
+ }
+#endif
+ monitor_->Enter();
+ }
+ void Exit() const {
+ monitor_->Exit();
+#if defined(DEBUG)
+ if (no_safepoint_scope_) {
+ Thread::Current()->DecrementNoSafepointScopeDepth();
+ }
+#endif
}
Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout) {
@@ -67,16 +186,29 @@ class MonitorLocker : public ValueObject {
private:
Monitor* const monitor_;
+ bool no_safepoint_scope_;
DISALLOW_COPY_AND_ASSIGN(MonitorLocker);
};
-
-// SafepointMutexLocker objects are used in code where the locks are
-// more coarse grained and a safepoint operation could be potentially
-// triggered while holding this lock. This ensures that other threads
-// which try to acquire the same lock will be marked as being at a
-// safepoint when they are blocked.
+/*
+ * Safepoint mutex locker :
+ * This locker abstraction should be used when the enclosing code could
+ * potentially trigger a safepoint.
+ * This locker ensures that other threads that try to acquire the same lock
+ * will be marked as being at a safepoint if they get blocked trying to
+ * acquire the lock.
+ * NOTE: please do not use the passed in mutex object independent of the locker
+ * class, For example the code below will not work correctly:
+ * {
+ * SafepointMutexLocker ml(m);
+ * ....
+ * m->Exit();
+ * ....
+ * m->Enter();
+ * ...
+ * }
+ */
class SafepointMutexLocker : public ValueObject {
public:
explicit SafepointMutexLocker(Mutex* mutex);
@@ -90,6 +222,39 @@ class SafepointMutexLocker : public ValueObject {
DISALLOW_COPY_AND_ASSIGN(SafepointMutexLocker);
};
+/*
+ * Safepoint monitor locker :
+ * This locker abstraction should be used when the enclosing code could
+ * potentially trigger a safepoint.
+ * This locker ensures that other threads that try to acquire the same lock
+ * will be marked as being at a safepoint if they get blocked trying to
+ * acquire the lock.
+ * NOTE: please do not use the passed in monitor object independent of the
+ * locker class, For example the code below will not work correctly:
+ * {
+ * SafepointMonitorLocker ml(m);
+ * ....
+ * m->Exit();
+ * ....
+ * m->Enter();
+ * ...
+ * }
+ */
+class SafepointMonitorLocker : public ValueObject {
+ public:
+ explicit SafepointMonitorLocker(Monitor* monitor);
+ virtual ~SafepointMonitorLocker() {
+ monitor_->Exit();
+ }
+
+ Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout);
+
+ private:
+ Monitor* const monitor_;
+
+ DISALLOW_COPY_AND_ASSIGN(SafepointMonitorLocker);
+};
+
} // namespace dart
« no previous file with comments | « runtime/vm/isolate.cc ('k') | runtime/vm/lockers.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698