Skip to content

Commit f63817f

Browse files
addaleaxtargos
authored andcommitted
worker: refactor thread id management
- Assign thread IDs to `Environment` instances, rather than Workers. This is more embedder-friendly than the current system, in which all “main threads” (if there are multiple ones) would get the id `0`. - Because that means that `isMainThread === (threadId === 0)` no longer holds, refactor `isMainThread` into a separate entity. Implement it in a way that allows for future extensibility, because we use `isMainThread` in multiple different ways (determining whether there is a parent thread; determining whether the current thread has control of the current process; etc.). PR-URL: #25796 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
1 parent b72ec23 commit f63817f

File tree

7 files changed

+46
-35
lines changed

7 files changed

+46
-35
lines changed

lib/internal/worker.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ const { pathToFileURL } = require('url');
3131

3232
const {
3333
Worker: WorkerImpl,
34-
threadId
34+
threadId,
35+
isMainThread
3536
} = internalBinding('worker');
3637

37-
const isMainThread = threadId === 0;
38-
3938
const kHandle = Symbol('kHandle');
4039
const kPublicPort = Symbol('kPublicPort');
4140
const kDispose = Symbol('kDispose');

src/api/environment.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
133133
// options than the global parse call.
134134
std::vector<std::string> args(argv, argv + argc);
135135
std::vector<std::string> exec_args(exec_argv, exec_argv + exec_argc);
136-
Environment* env = new Environment(isolate_data, context);
136+
// TODO(addaleax): Provide more sensible flags, in an embedder-accessible way.
137+
Environment* env =
138+
new Environment(isolate_data, context, Environment::kIsMainThread);
137139
env->Start(per_process::v8_is_profiling);
138140
env->ProcessCliArgs(args, exec_args);
139141
return env;

src/env-inl.h

+1-5
Original file line numberDiff line numberDiff line change
@@ -647,17 +647,13 @@ inline void Environment::set_has_run_bootstrapping_code(bool value) {
647647
}
648648

649649
inline bool Environment::is_main_thread() const {
650-
return thread_id_ == 0;
650+
return flags_ & kIsMainThread;
651651
}
652652

653653
inline uint64_t Environment::thread_id() const {
654654
return thread_id_;
655655
}
656656

657-
inline void Environment::set_thread_id(uint64_t id) {
658-
thread_id_ = id;
659-
}
660-
661657
inline worker::Worker* Environment::worker_context() const {
662658
return worker_context_;
663659
}

src/env.cc

+7-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <stdio.h>
1818
#include <algorithm>
19+
#include <atomic>
1920

2021
namespace node {
2122

@@ -166,8 +167,11 @@ void Environment::TrackingTraceStateObserver::UpdateTraceCategoryState() {
166167
0, nullptr).ToLocalChecked();
167168
}
168169

170+
static std::atomic<uint64_t> next_thread_id{0};
171+
169172
Environment::Environment(IsolateData* isolate_data,
170-
Local<Context> context)
173+
Local<Context> context,
174+
Flags flags)
171175
: isolate_(context->GetIsolate()),
172176
isolate_data_(isolate_data),
173177
immediate_info_(context->GetIsolate()),
@@ -176,6 +180,8 @@ Environment::Environment(IsolateData* isolate_data,
176180
should_abort_on_uncaught_toggle_(isolate_, 1),
177181
trace_category_state_(isolate_, kTraceCategoryCount),
178182
stream_base_state_(isolate_, StreamBase::kNumStreamBaseStateFields),
183+
flags_(flags),
184+
thread_id_(next_thread_id++),
179185
fs_stats_field_array_(isolate_, kFsStatsBufferLength),
180186
fs_stats_field_bigint_array_(isolate_, kFsStatsBufferLength),
181187
context_(context->GetIsolate(), context) {

src/env.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,11 @@ class Environment {
593593
DISALLOW_COPY_AND_ASSIGN(TickInfo);
594594
};
595595

596+
enum Flags {
597+
kNoFlags = 0,
598+
kIsMainThread = 1
599+
};
600+
596601
static inline Environment* GetCurrent(v8::Isolate* isolate);
597602
static inline Environment* GetCurrent(v8::Local<v8::Context> context);
598603
static inline Environment* GetCurrent(
@@ -606,7 +611,8 @@ class Environment {
606611
static inline Environment* GetThreadLocalEnv();
607612

608613
Environment(IsolateData* isolate_data,
609-
v8::Local<v8::Context> context);
614+
v8::Local<v8::Context> context,
615+
Flags flags = Flags());
610616
~Environment();
611617

612618
void Start(bool start_profiler_idle_notifier);
@@ -759,7 +765,6 @@ class Environment {
759765

760766
inline bool is_main_thread() const;
761767
inline uint64_t thread_id() const;
762-
inline void set_thread_id(uint64_t id);
763768
inline worker::Worker* worker_context() const;
764769
inline void set_worker_context(worker::Worker* context);
765770
inline void add_sub_worker_context(worker::Worker* context);
@@ -1003,7 +1008,8 @@ class Environment {
10031008

10041009
bool has_run_bootstrapping_code_ = false;
10051010
bool can_call_into_js_ = true;
1006-
uint64_t thread_id_ = 0;
1011+
Flags flags_;
1012+
uint64_t thread_id_;
10071013
std::unordered_set<worker::Worker*> sub_worker_contexts_;
10081014

10091015
static void* const kNodeContextTagPtr;

src/node.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
743743
HandleScope handle_scope(isolate);
744744
Local<Context> context = NewContext(isolate);
745745
Context::Scope context_scope(context);
746-
Environment env(isolate_data, context);
746+
Environment env(isolate_data, context, Environment::kIsMainThread);
747747
env.Start(per_process::v8_is_profiling);
748748
env.ProcessCliArgs(args, exec_args);
749749

src/node_worker.cc

+23-21
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
using node::options_parser::kDisallowedInEnvironment;
1515
using v8::ArrayBuffer;
16+
using v8::Boolean;
1617
using v8::Context;
1718
using v8::Function;
1819
using v8::FunctionCallbackInfo;
@@ -33,9 +34,6 @@ namespace worker {
3334

3435
namespace {
3536

36-
uint64_t next_thread_id = 1;
37-
Mutex next_thread_id_mutex;
38-
3937
#if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR
4038
void StartWorkerInspector(Environment* child, const std::string& url) {
4139
child->inspector_agent()->Start(url,
@@ -74,17 +72,7 @@ Worker::Worker(Environment* env,
7472
const std::string& url,
7573
std::shared_ptr<PerIsolateOptions> per_isolate_opts)
7674
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_WORKER), url_(url) {
77-
// Generate a new thread id.
78-
{
79-
Mutex::ScopedLock next_thread_id_lock(next_thread_id_mutex);
80-
thread_id_ = next_thread_id++;
81-
}
82-
83-
Debug(this, "Creating worker with id %llu", thread_id_);
84-
wrap->Set(env->context(),
85-
env->thread_id_string(),
86-
Number::New(env->isolate(),
87-
static_cast<double>(thread_id_))).FromJust();
75+
Debug(this, "Creating new worker instance at %p", static_cast<void*>(this));
8876

8977
// Set up everything that needs to be set up in the parent environment.
9078
parent_port_ = MessagePort::New(env, env->context());
@@ -130,7 +118,7 @@ Worker::Worker(Environment* env,
130118
CHECK_NE(env_, nullptr);
131119
env_->set_abort_on_uncaught_exception(false);
132120
env_->set_worker_context(this);
133-
env_->set_thread_id(thread_id_);
121+
thread_id_ = env_->thread_id();
134122

135123
env_->Start(env->profiler_idle_notifier_started());
136124
env_->ProcessCliArgs(std::vector<std::string>{},
@@ -142,7 +130,15 @@ Worker::Worker(Environment* env,
142130
// The new isolate won't be bothered on this thread again.
143131
isolate_->DiscardThreadSpecificMetadata();
144132

145-
Debug(this, "Set up worker with id %llu", thread_id_);
133+
wrap->Set(env->context(),
134+
env->thread_id_string(),
135+
Number::New(env->isolate(), static_cast<double>(thread_id_)))
136+
.FromJust();
137+
138+
Debug(this,
139+
"Set up worker at %p with id %llu",
140+
static_cast<void*>(this),
141+
thread_id_);
146142
}
147143

148144
bool Worker::is_stopped() const {
@@ -562,11 +558,17 @@ void InitWorker(Local<Object> target,
562558

563559
env->SetMethod(target, "getEnvMessagePort", GetEnvMessagePort);
564560

565-
auto thread_id_string = FIXED_ONE_BYTE_STRING(env->isolate(), "threadId");
566-
target->Set(env->context(),
567-
thread_id_string,
568-
Number::New(env->isolate(),
569-
static_cast<double>(env->thread_id()))).FromJust();
561+
target
562+
->Set(env->context(),
563+
env->thread_id_string(),
564+
Number::New(env->isolate(), static_cast<double>(env->thread_id())))
565+
.FromJust();
566+
567+
target
568+
->Set(env->context(),
569+
FIXED_ONE_BYTE_STRING(env->isolate(), "isMainThread"),
570+
Boolean::New(env->isolate(), env->is_main_thread()))
571+
.FromJust();
570572
}
571573

572574
} // anonymous namespace

0 commit comments

Comments
 (0)