fix taskpools shared between parent and child process

should recreate taskpools for child process
issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5EG9W?from=project-issue

Signed-off-by: lukai <lukai25@huawei.com>
Change-Id: If98b0938af358a3949fb1f5f809467737761b792
This commit is contained in:
lukai 2022-07-05 14:15:02 +08:00
parent de2b4a87f1
commit 3d956047cf
12 changed files with 85 additions and 7 deletions

View File

@ -106,6 +106,19 @@ bool EcmaVM::Destroy(EcmaVM *vm)
return false;
}
void EcmaVM::preFork()
{
heap_->CompactHeapBeforeFork();
heap_->GetReadOnlySpace()->SetReadOnly();
heap_->DisableParallelGC();
}
void EcmaVM::postFork()
{
GetAssociatedJSThread()->SetThreadId();
Taskpool::GetCurrentTaskpool()->Initialize();
}
EcmaVM::EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config)
: stringTable_(new EcmaStringTable(this)),
nativeAreaAllocator_(std::make_unique<NativeAreaAllocator>()),
@ -192,7 +205,6 @@ bool EcmaVM::Initialize()
if (options_.GetEnableAsmInterpreter() && options_.WasAOTOutputFileSet()) {
LoadAOTFiles();
}
heap_->GetReadOnlySpace()->SetReadOnly();
InitializeFinish();
return true;
}
@ -624,7 +636,7 @@ void EcmaVM::ClearBufferData()
bool EcmaVM::ExecutePromisePendingJob()
{
if (isProcessingPendingJob_) {
LOG_ECMA(ERROR) << "EcmaVM::ExecutePromisePendingJob can not reentrant";
LOG_ECMA(DEBUG) << "EcmaVM::ExecutePromisePendingJob can not reentrant";
return false;
}
if (!thread_->HasPendingException()) {

View File

@ -113,7 +113,6 @@ public:
}
bool Initialize();
bool InitializeFinish();
GCStats *GetEcmaGCStats() const
@ -348,6 +347,8 @@ public:
exceptionBCList_.clear();
}
void preFork();
void postFork();
protected:
void HandleUncaughtException(TaggedObject *exception);

View File

@ -393,6 +393,11 @@ public:
return id_.load(std::memory_order_relaxed);
}
void SetThreadId()
{
id_.store(JSThread::GetCurrentThreadId(), std::memory_order_relaxed);
}
static ThreadId GetCurrentThreadId()
{
return os::thread::GetCurrentThreadId();

View File

@ -58,6 +58,12 @@ public:
return enableMarkType_ == EnableConcurrentMarkType::DISABLE ||
enableMarkType_ == EnableConcurrentMarkType::CONFIG_DISABLE;
}
void DisableConcurrentMark()
{
enableMarkType_ = EnableConcurrentMarkType::CONFIG_DISABLE;
}
bool IsRequestDisabled() const
{
return enableMarkType_ == EnableConcurrentMarkType::REQUEST_DISABLE;

View File

@ -65,6 +65,11 @@ public:
return !IsDisabled();
}
void DisableConcurrentSweep()
{
enableType_ = EnableConcurrentSweepType::CONFIG_DISABLE;
}
bool IsDisabled() const
{
return enableType_ == EnableConcurrentSweepType::DISABLE ||

View File

@ -90,7 +90,10 @@ void FullGC::Sweep()
{
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "FullGC::Sweep");
// process weak reference
auto totalThreadCount = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum() + 1; // gc thread and main thread
uint32_t totalThreadCount = 1; // 1 : mainthread
if (heap_->IsParallelGCEnabled()) {
totalThreadCount += Taskpool::GetCurrentTaskpool()->GetTotalThreadNum();
}
for (uint32_t i = 0; i < totalThreadCount; i++) {
ProcessQueue *queue = workManager_->GetWeakReferenceQueue(i);

View File

@ -280,6 +280,18 @@ void Heap::CompactHeapBeforeFork()
fullGC_->RunPhasesForAppSpawn();
}
void Heap::DisableParallelGC()
{
Prepare();
parallelGC_ = false;
maxEvacuateTaskCount_ = 0;
maxMarkTaskCount_ = 0;
stwYoungGC_->DisableParallelGC();
sweeper_->DisableConcurrentSweep();
concurrentMarker_ ->DisableConcurrentMark();
Taskpool::GetCurrentTaskpool()->Destroy();
}
TriggerGCType Heap::SelectGCType() const
{
// If concurrent mark is enabled, the TryTriggerConcurrentMarking decide which GC to choose.

View File

@ -61,6 +61,7 @@ public:
void Prepare();
void Resume(TriggerGCType gcType);
void CompactHeapBeforeFork();
void DisableParallelGC();
// fixme: Rename NewSpace to YoungSpace.
// This is the active young generation space that the new objects are allocated in
// or copied into (from the other semi space) during semi space GC.

View File

@ -40,6 +40,10 @@ public:
NO_COPY_SEMANTIC(STWYoungGC);
NO_MOVE_SEMANTIC(STWYoungGC);
void DisableParallelGC()
{
parallelGC_ = false;
}
virtual void RunPhases() override;
protected:

View File

@ -1146,6 +1146,8 @@ public:
static void InitializeMemMapAllocator();
static void DestroyMemMapAllocator();
static EcmaVM* CreateEcmaVM(const ecmascript::JSRuntimeOptions &options);
static void preFork(EcmaVM *vm);
static void postFork(EcmaVM *vm);
private:
static int vmCount_;
static bool initialize_;

View File

@ -292,6 +292,16 @@ bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size,
return true;
}
void JSNApi::preFork(EcmaVM *vm)
{
vm->preFork();
}
void JSNApi::postFork(EcmaVM *vm)
{
vm->postFork();
}
Local<ObjectRef> JSNApi::GetUncaughtException(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<ObjectRef>(vm->GetEcmaUncaughtException());

View File

@ -95,6 +95,7 @@ public:
HWTEST_F_L0(ReadOnlySpaceTest, ReadOnlyTest)
{
auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetReadOnlySpace()->SetReadOnly();
if (ReadOnlyTestManager::RegisterSignal() == -1) {
perror("sigaction error");
exit(1);
@ -112,7 +113,6 @@ HWTEST_F_L0(ReadOnlySpaceTest, ReadOnlyTest)
HWTEST_F_L0(ReadOnlySpaceTest, AllocateTest)
{
auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetReadOnlySpace()->ClearReadOnly();
auto *object = heap->AllocateReadOnlyOrHugeObject(
JSHClass::Cast(thread->GlobalConstants()->GetBigIntClass().GetTaggedObject()));
auto *region = Region::ObjectAddressToRange(object);
@ -122,7 +122,6 @@ HWTEST_F_L0(ReadOnlySpaceTest, AllocateTest)
HWTEST_F_L0(ReadOnlySpaceTest, CompactHeapBeforeForkTest)
{
auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetReadOnlySpace()->ClearReadOnly();
std::string rawStr = "test string";
JSHandle<EcmaString> string = factory->NewFromStdString(rawStr);
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
@ -140,7 +139,6 @@ HWTEST_F_L0(ReadOnlySpaceTest, CompactHeapBeforeForkTest)
HWTEST_F_L0(ReadOnlySpaceTest, GCTest)
{
auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
heap->GetReadOnlySpace()->ClearReadOnly();
auto *object = heap->AllocateReadOnlyOrHugeObject(
JSHClass::Cast(thread->GlobalConstants()->GetBigIntClass().GetTaggedObject()));
heap->CollectGarbage(TriggerGCType::YOUNG_GC);
@ -149,4 +147,23 @@ HWTEST_F_L0(ReadOnlySpaceTest, GCTest)
auto *region = Region::ObjectAddressToRange(object);
EXPECT_TRUE(region->InReadOnlySpace());
}
HWTEST_F_L0(ReadOnlySpaceTest, ForkTest)
{
auto vm = thread->GetEcmaVM();
auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
std::string rawStr = "fork string";
JSHandle<EcmaString> string = factory->NewFromStdString(rawStr);
JSNApi::preFork(vm);
if (fork() != 0) {
// test gc in parent process
heap->CollectGarbage(TriggerGCType::OLD_GC);
} else {
JSNApi::postFork(vm);
// test gc in child process
heap->CollectGarbage(TriggerGCType::OLD_GC);
auto *region = Region::ObjectAddressToRange(string.GetObject<TaggedObject>());
EXPECT_TRUE(region->InReadOnlySpace());
}
}
} // namespace panda::test