| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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_THREAD_REGISTRY_H_ | 5 #ifndef VM_THREAD_REGISTRY_H_ |
| 6 #define VM_THREAD_REGISTRY_H_ | 6 #define VM_THREAD_REGISTRY_H_ |
| 7 | 7 |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #include "vm/growable_array.h" | 9 #include "vm/growable_array.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| 11 #include "vm/lockers.h" | 11 #include "vm/lockers.h" |
| 12 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
| 13 #include "vm/thread.h" | 13 #include "vm/thread.h" |
| 14 | 14 |
| 15 namespace dart { | 15 namespace dart { |
| 16 | 16 |
| 17 // Unordered collection of threads relating to a particular isolate. | 17 // Unordered collection of threads relating to a particular isolate. |
| 18 class ThreadRegistry { | 18 class ThreadRegistry { |
| 19 public: | 19 public: |
| 20 ThreadRegistry() | 20 ThreadRegistry() |
| 21 : monitor_(new Monitor()), | 21 : threads_lock_(new Monitor()), |
| 22 active_list_(NULL), | 22 active_list_(NULL), |
| 23 free_list_(NULL), | 23 free_list_(NULL), |
| 24 mutator_thread_(NULL), | 24 mutator_thread_(NULL) {} |
| 25 in_rendezvous_(false), | |
| 26 remaining_(0), | |
| 27 round_(0) {} | |
| 28 | |
| 29 ~ThreadRegistry(); | 25 ~ThreadRegistry(); |
| 30 | 26 |
| 31 Thread* active_list() const { return active_list_; } | |
| 32 | |
| 33 // Bring all threads in this isolate to a safepoint. The caller is | |
| 34 // expected to be implicitly at a safepoint. The threads will wait | |
| 35 // until ResumeAllThreads is called. First participates in any | |
| 36 // already pending rendezvous requested by another thread. Any | |
| 37 // thread that tries to enter this isolate during rendezvous will | |
| 38 // wait in RestoreStateTo. Nesting is not supported: the caller must | |
| 39 // call ResumeAllThreads before making further calls to | |
| 40 // SafepointThreads. | |
| 41 void SafepointThreads(); | |
| 42 | |
| 43 // Unblocks all threads participating in the rendezvous that was organized | |
| 44 // by a prior call to SafepointThreads. | |
| 45 // TODO(koda): Consider adding a scope helper to avoid omitting this call. | |
| 46 void ResumeAllThreads(); | |
| 47 | |
| 48 // Indicate that the current thread is at a safepoint, and offer to wait for | |
| 49 // any pending rendezvous request (if none, returns immediately). | |
| 50 void CheckSafepoint() { | |
| 51 MonitorLocker ml(monitor_); | |
| 52 CheckSafepointLocked(); | |
| 53 } | |
| 54 | |
| 55 bool AtSafepoint() const { return in_rendezvous_; } | |
| 56 Thread* Schedule(Isolate* isolate, bool is_mutator, bool bypass_safepoint); | |
| 57 void Unschedule(Thread* thread, bool is_mutator, bool bypass_safepoint); | |
| 58 void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames); | 27 void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames); |
| 59 void PrepareForGC(); | 28 void PrepareForGC(); |
| 60 | 29 |
| 61 private: | 30 private: |
| 62 void AddThreadToActiveList(Thread* thread); | 31 Thread* active_list() const { return active_list_; } |
| 63 void RemoveThreadFromActiveList(Thread* thread); | 32 Monitor* threads_lock() const { return threads_lock_; } |
| 64 Thread* GetThreadFromFreelist(Isolate* isolate); | |
| 65 void ReturnThreadToFreelist(Thread* thread); | |
| 66 | 33 |
| 67 // Note: Lock should be taken before this function is called. | 34 Thread* GetFreeThreadLocked(Isolate* isolate, bool is_mutator); |
| 68 void CheckSafepointLocked(); | 35 void ReturnThreadLocked(bool is_mutator, Thread* thread); |
| 36 void AddToActiveListLocked(Thread* thread); |
| 37 void RemoveFromActiveListLocked(Thread* thread); |
| 38 Thread* GetFromFreelistLocked(Isolate* isolate); |
| 39 void ReturnToFreelistLocked(Thread* thread); |
| 69 | 40 |
| 70 // Returns the number threads that are scheduled on this isolate. | 41 // This monitor protects the threads list for an isolate, it is used whenever |
| 71 // Note: Lock should be taken before this function is called. | 42 // we need to iterate over threads (both active and free) in an isolate. |
| 72 intptr_t CountScheduledLocked(); | 43 Monitor* threads_lock_; |
| 73 | |
| 74 Monitor* monitor_; // All access is synchronized through this monitor. | |
| 75 Thread* active_list_; // List of active threads in the isolate. | 44 Thread* active_list_; // List of active threads in the isolate. |
| 76 Thread* free_list_; // Free list of Thread objects that can be reused. | 45 Thread* free_list_; // Free list of Thread objects that can be reused. |
| 46 |
| 77 // TODO(asiva): Currently we treat a mutator thread as a special thread | 47 // TODO(asiva): Currently we treat a mutator thread as a special thread |
| 78 // and always schedule execution of Dart code on the same mutator thread | 48 // and always schedule execution of Dart code on the same mutator thread |
| 79 // object. The ApiLocalScope has been made thread specific but we still | 49 // object. The ApiLocalScope has been made thread specific but we still |
| 80 // have scenarios where we do a temporary exit of an Isolate with live | 50 // have scenarios where we do a temporary exit of an Isolate with live |
| 81 // zones/handles in the the API scope : | 51 // zones/handles in the the API scope : |
| 82 // - Dart_RunLoop() | 52 // - Dart_RunLoop() |
| 83 // - IsolateSaver in Dart_NewNativePort | 53 // - IsolateSaver in Dart_NewNativePort |
| 84 // - Isolate spawn (function/uri) under FLAG_i_like_slow_isolate_spawn | 54 // - Isolate spawn (function/uri) under FLAG_i_like_slow_isolate_spawn |
| 85 // We probably need a mechanism to return to the specific thread only | 55 // We probably need a mechanism to return to the specific thread only |
| 86 // for these specific cases. We should also determine if the embedder | 56 // for these specific cases. We should also determine if the embedder |
| 87 // should allow exiting an isolate with live state in zones/handles in | 57 // should allow exiting an isolate with live state in zones/handles in |
| 88 // which case a new API for returning to the specific thread needs to be | 58 // which case a new API for returning to the specific thread needs to be |
| 89 // added. | 59 // added. |
| 90 Thread* mutator_thread_; | 60 Thread* mutator_thread_; |
| 91 | 61 |
| 92 // Safepoint rendezvous state. | 62 friend class Isolate; |
| 93 bool in_rendezvous_; // A safepoint rendezvous request is in progress. | 63 friend class SafepointHandler; |
| 94 intptr_t remaining_; // Number of threads yet to reach their safepoint. | |
| 95 int64_t round_; // Counter, to prevent missing updates to remaining_ | |
| 96 // (see comments in CheckSafepointLocked). | |
| 97 | |
| 98 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry); | 64 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry); |
| 99 }; | 65 }; |
| 100 | 66 |
| 101 } // namespace dart | 67 } // namespace dart |
| 102 | 68 |
| 103 #endif // VM_THREAD_REGISTRY_H_ | 69 #endif // VM_THREAD_REGISTRY_H_ |
| OLD | NEW |