1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_EXECUTION_V8THREADS_H_
6#define V8_EXECUTION_V8THREADS_H_
7
8#include <atomic>
9
10#include "src/execution/isolate.h"
11
12namespace v8 {
13namespace internal {
14
15class RootVisitor;
16class ThreadLocalTop;
17
18class ThreadState {
19 public:
20  // Returns nullptr after the last one.
21  ThreadState* Next();
22
23  enum List { FREE_LIST, IN_USE_LIST };
24
25  void LinkInto(List list);
26  void Unlink();
27
28  // Id of thread.
29  void set_id(ThreadId id) { id_ = id; }
30  ThreadId id() { return id_; }
31
32  // Get data area for archiving a thread.
33  char* data() { return data_; }
34
35 private:
36  explicit ThreadState(ThreadManager* thread_manager);
37  ~ThreadState();
38
39  void AllocateSpace();
40
41  ThreadId id_;
42  char* data_;
43  ThreadState* next_;
44  ThreadState* previous_;
45
46  ThreadManager* thread_manager_;
47
48  friend class ThreadManager;
49};
50
51class ThreadVisitor {
52 public:
53  // ThreadLocalTop may be only available during this call.
54  virtual void VisitThread(Isolate* isolate, ThreadLocalTop* top) = 0;
55
56 protected:
57  virtual ~ThreadVisitor() = default;
58};
59
60class ThreadManager {
61 public:
62  void Lock();
63  V8_EXPORT_PRIVATE void Unlock();
64
65  void InitThread(const ExecutionAccess&);
66  void ArchiveThread();
67  bool RestoreThread();
68  void FreeThreadResources();
69  bool IsArchived();
70
71  void Iterate(RootVisitor* v);
72  void IterateArchivedThreads(ThreadVisitor* v);
73  bool IsLockedByCurrentThread() const {
74    return mutex_owner_.load(std::memory_order_relaxed) == ThreadId::Current();
75  }
76  bool IsLockedByThread(ThreadId id) const {
77    return mutex_owner_.load(std::memory_order_relaxed) == id;
78  }
79
80  ThreadId CurrentId();
81
82  // Iterate over in-use states.
83  ThreadState* FirstThreadStateInUse();
84  ThreadState* GetFreeThreadState();
85
86 private:
87  explicit ThreadManager(Isolate* isolate);
88  ~ThreadManager();
89
90  void DeleteThreadStateList(ThreadState* anchor);
91
92  void EagerlyArchiveThread();
93
94  base::Mutex mutex_;
95  // {ThreadId} must be trivially copyable to be stored in {std::atomic}.
96  ASSERT_TRIVIALLY_COPYABLE(i::ThreadId);
97  std::atomic<ThreadId> mutex_owner_;
98  ThreadId lazily_archived_thread_;
99  ThreadState* lazily_archived_thread_state_;
100
101  // In the following two lists there is always at least one object on the list.
102  // The first object is a flying anchor that is only there to simplify linking
103  // and unlinking.
104  // Head of linked list of free states.
105  ThreadState* free_anchor_;
106  // Head of linked list of states in use.
107  ThreadState* in_use_anchor_;
108
109  Isolate* isolate_;
110
111  friend class Isolate;
112  friend class ThreadState;
113};
114
115}  // namespace internal
116}  // namespace v8
117
118#endif  // V8_EXECUTION_V8THREADS_H_
119