11cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_EXECUTION_V8THREADS_H_
61cb0ef41Sopenharmony_ci#define V8_EXECUTION_V8THREADS_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <atomic>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/execution/isolate.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciclass RootVisitor;
161cb0ef41Sopenharmony_ciclass ThreadLocalTop;
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciclass ThreadState {
191cb0ef41Sopenharmony_ci public:
201cb0ef41Sopenharmony_ci  // Returns nullptr after the last one.
211cb0ef41Sopenharmony_ci  ThreadState* Next();
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  enum List { FREE_LIST, IN_USE_LIST };
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  void LinkInto(List list);
261cb0ef41Sopenharmony_ci  void Unlink();
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  // Id of thread.
291cb0ef41Sopenharmony_ci  void set_id(ThreadId id) { id_ = id; }
301cb0ef41Sopenharmony_ci  ThreadId id() { return id_; }
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  // Get data area for archiving a thread.
331cb0ef41Sopenharmony_ci  char* data() { return data_; }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci private:
361cb0ef41Sopenharmony_ci  explicit ThreadState(ThreadManager* thread_manager);
371cb0ef41Sopenharmony_ci  ~ThreadState();
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  void AllocateSpace();
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  ThreadId id_;
421cb0ef41Sopenharmony_ci  char* data_;
431cb0ef41Sopenharmony_ci  ThreadState* next_;
441cb0ef41Sopenharmony_ci  ThreadState* previous_;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  ThreadManager* thread_manager_;
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  friend class ThreadManager;
491cb0ef41Sopenharmony_ci};
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ciclass ThreadVisitor {
521cb0ef41Sopenharmony_ci public:
531cb0ef41Sopenharmony_ci  // ThreadLocalTop may be only available during this call.
541cb0ef41Sopenharmony_ci  virtual void VisitThread(Isolate* isolate, ThreadLocalTop* top) = 0;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci protected:
571cb0ef41Sopenharmony_ci  virtual ~ThreadVisitor() = default;
581cb0ef41Sopenharmony_ci};
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciclass ThreadManager {
611cb0ef41Sopenharmony_ci public:
621cb0ef41Sopenharmony_ci  void Lock();
631cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE void Unlock();
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  void InitThread(const ExecutionAccess&);
661cb0ef41Sopenharmony_ci  void ArchiveThread();
671cb0ef41Sopenharmony_ci  bool RestoreThread();
681cb0ef41Sopenharmony_ci  void FreeThreadResources();
691cb0ef41Sopenharmony_ci  bool IsArchived();
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  void Iterate(RootVisitor* v);
721cb0ef41Sopenharmony_ci  void IterateArchivedThreads(ThreadVisitor* v);
731cb0ef41Sopenharmony_ci  bool IsLockedByCurrentThread() const {
741cb0ef41Sopenharmony_ci    return mutex_owner_.load(std::memory_order_relaxed) == ThreadId::Current();
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci  bool IsLockedByThread(ThreadId id) const {
771cb0ef41Sopenharmony_ci    return mutex_owner_.load(std::memory_order_relaxed) == id;
781cb0ef41Sopenharmony_ci  }
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  ThreadId CurrentId();
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  // Iterate over in-use states.
831cb0ef41Sopenharmony_ci  ThreadState* FirstThreadStateInUse();
841cb0ef41Sopenharmony_ci  ThreadState* GetFreeThreadState();
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci private:
871cb0ef41Sopenharmony_ci  explicit ThreadManager(Isolate* isolate);
881cb0ef41Sopenharmony_ci  ~ThreadManager();
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  void DeleteThreadStateList(ThreadState* anchor);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  void EagerlyArchiveThread();
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  base::Mutex mutex_;
951cb0ef41Sopenharmony_ci  // {ThreadId} must be trivially copyable to be stored in {std::atomic}.
961cb0ef41Sopenharmony_ci  ASSERT_TRIVIALLY_COPYABLE(i::ThreadId);
971cb0ef41Sopenharmony_ci  std::atomic<ThreadId> mutex_owner_;
981cb0ef41Sopenharmony_ci  ThreadId lazily_archived_thread_;
991cb0ef41Sopenharmony_ci  ThreadState* lazily_archived_thread_state_;
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  // In the following two lists there is always at least one object on the list.
1021cb0ef41Sopenharmony_ci  // The first object is a flying anchor that is only there to simplify linking
1031cb0ef41Sopenharmony_ci  // and unlinking.
1041cb0ef41Sopenharmony_ci  // Head of linked list of free states.
1051cb0ef41Sopenharmony_ci  ThreadState* free_anchor_;
1061cb0ef41Sopenharmony_ci  // Head of linked list of states in use.
1071cb0ef41Sopenharmony_ci  ThreadState* in_use_anchor_;
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  Isolate* isolate_;
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  friend class Isolate;
1121cb0ef41Sopenharmony_ci  friend class ThreadState;
1131cb0ef41Sopenharmony_ci};
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci}  // namespace internal
1161cb0ef41Sopenharmony_ci}  // namespace v8
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci#endif  // V8_EXECUTION_V8THREADS_H_
119