!9826 pthread_mutex_t对接ffrt

Merge pull request !9826 from chentianyu/ffrt
This commit is contained in:
openharmony_ci 2024-10-18 12:53:51 +00:00 committed by Gitee
commit 603c6825a2
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 240 additions and 5 deletions

View File

@ -998,7 +998,7 @@ ecma_platform_source += [
"ecmascript/platform/common/map.cpp",
"ecmascript/platform/common/mutex.cpp",
"ecmascript/platform/common/filesystem.cpp",
"ecmascript/platform/common/ffrt.cpp",
"ecmascript/platform/common/ffrt_adapter.cpp",
]
config("include_llvm") {

View File

@ -22,7 +22,7 @@
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/platform/ffrt.h"
#include "ecmascript/platform/ffrt_adapter.h"
#if defined(ENABLE_FFRT_INTERFACES)
#include "c/executor_task.h"

View File

@ -753,7 +753,11 @@ void JSThread::CheckAndPassActiveBarrier()
bool JSThread::PassSuspendBarrier()
{
// Use suspendLock_ to avoid data-race between suspend-all-thread and suspended-threads.
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder hock(suspendLock_);
#else
LockHolder lock(suspendLock_);
#endif
if (suspendBarrier_ != nullptr) {
suspendBarrier_->PassStrongly();
suspendBarrier_ = nullptr;
@ -1152,7 +1156,11 @@ void JSThread::UpdateState(ThreadState newState)
void JSThread::SuspendThread(bool internalSuspend, SuspendBarrier* barrier)
{
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder hock(suspendLock_);
#else
LockHolder lock(suspendLock_);
#endif
if (!internalSuspend) {
// do smth here if we want to combine internal and external suspension
}
@ -1173,7 +1181,11 @@ void JSThread::SuspendThread(bool internalSuspend, SuspendBarrier* barrier)
void JSThread::ResumeThread(bool internalSuspend)
{
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder hock(suspendLock_);
#else
LockHolder lock(suspendLock_);
#endif
if (!internalSuspend) {
// do smth here if we want to combine internal and external suspension
}
@ -1194,7 +1206,11 @@ void JSThread::WaitSuspension()
UpdateState(ThreadState::IS_SUSPENDED);
{
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SuspendTime::WaitSuspension");
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(suspendLock_);
#else
LockHolder lock(suspendLock_);
#endif
while (suspendCount_ > 0) {
suspendCondVar_.TimedWait(&suspendLock_, TIMEOUT);
// we need to do smth if Runtime is terminating at this point
@ -1286,7 +1302,11 @@ void JSThread::StoreRunningState(ThreadState newState)
} else if ((oldStateAndFlags.asNonvolatileStruct.flags & ThreadFlag::SUSPEND_REQUEST) != 0) {
constexpr int TIMEOUT = 100;
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SuspendTime::StoreRunningState");
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(suspendLock_);
#else
LockHolder lock(suspendLock_);
#endif
while (suspendCount_ > 0) {
suspendCondVar_.TimedWait(&suspendLock_, TIMEOUT);
}

View File

@ -21,7 +21,7 @@
#include <string>
#include <cstdint>
#include "ecmascript/platform/ffrt.h"
#include "ecmascript/platform/ffrt_adapter.h"
#include "ecmascript/base/aligned_struct.h"
#include "ecmascript/builtin_entries.h"
#include "ecmascript/daemon/daemon_task.h"
@ -37,6 +37,7 @@
#if defined(ENABLE_FFRT_INTERFACES)
#include "ffrt.h"
#include "c/executor_task.h"
#include "ecmascript/platform/ffrt_mutex.h"
#endif
namespace panda::ecmascript {
@ -1609,9 +1610,14 @@ private:
CVector<EcmaContext *> contexts_;
EcmaContext *currentContext_ {nullptr};
#if defined(ENABLE_FFRT_INTERFACES)
FFRTMutex suspendLock_;
FFRTConditionVariable suspendCondVar_;
#else
Mutex suspendLock_;
int32_t suspendCount_ {0};
ConditionVariable suspendCondVar_;
#endif
int32_t suspendCount_ {0};
SuspendBarrier *suspendBarrier_ {nullptr};
uint64_t jobId_ {0};

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "ecmascript/platform/ffrt.h"
#include "ecmascript/platform/ffrt_adapter.h"
#include "libpandabase/os/thread.h"
#if defined(ENABLE_FFRT_INTERFACES)

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_PLATFORM_FFRT_MUTEX_H
#define ECMASCRIPT_PLATFORM_FFRT_MUTEX_H
#include "ffrt.h"
#include "ecmascript/common.h"
#ifdef DEBUG
#define FATAL_IF_ERROR(f, rc) \
do { \
if (rc != 0) { \
LOG_ECMA(FATAL)<< f << " failed: " << rc; \
} \
} while (false)
#else
#define FATAL_IF_ERROR(f, rc) static_cast<void>(0)
#endif
namespace panda::ecmascript {
class PUBLIC_API FFRTMutex {
public:
explicit FFRTMutex(bool is_init = true)
{
if (is_init) {
Init(nullptr);
}
}
~FFRTMutex()
{
[[maybe_unused]]int rc = ffrt_mutex_destroy(&mutex_);
FATAL_IF_ERROR("ffrt_mutex_destroy", rc);
}
void Lock()
{
[[maybe_unused]]int rc = ffrt_mutex_lock(&mutex_);
FATAL_IF_ERROR("ffrt_mutex_lock", rc);
}
bool TryLock()
{
int rc = ffrt_mutex_trylock(&mutex_);
if (rc == EBUSY) {
return false;
}
FATAL_IF_ERROR("ffrt_mutex_trylock", rc);
return true;
}
void Unlock()
{
[[maybe_unused]]int rc = ffrt_mutex_unlock(&mutex_);
FATAL_IF_ERROR("ffrt_mutex_unlock", rc);
}
protected:
void Init(ffrt_mutexattr_t *attrs)
{
[[maybe_unused]]int rc = ffrt_mutex_init(&mutex_, attrs);
FATAL_IF_ERROR("ffrt_mutex_init", rc);
}
private:
ffrt_mutex_t mutex_;
friend class FFRTConditionVariable;
};
class PUBLIC_API FFRTConditionVariable {
public:
FFRTConditionVariable()
{
[[maybe_unused]]int rc = ffrt_cond_init(&cond_, nullptr);
FATAL_IF_ERROR("ffrt_cond_init", rc);
}
~FFRTConditionVariable()
{
[[maybe_unused]]int rc = ffrt_cond_destroy(&cond_);
FATAL_IF_ERROR("ffrt_cond_destroy", rc);
}
void Signal()
{
[[maybe_unused]]int rc = ffrt_cond_signal(&cond_);
FATAL_IF_ERROR("ffrt_cond_signal", rc);
}
void SignalAll()
{
[[maybe_unused]]int rc = ffrt_cond_broadcast(&cond_);
FATAL_IF_ERROR("ffrt_cond_broadcast", rc);
}
void Wait(FFRTMutex *mutex)
{
[[maybe_unused]]int rc = ffrt_cond_wait(&cond_, &mutex->mutex_);
FATAL_IF_ERROR("ffrt_cond_wait", rc);
}
bool TimedWait(FFRTMutex *mutex, uint64_t ms, uint64_t ns = 0, bool is_absolute = false)
{
struct timespec abs_time = ConvertTime(ms, ns, is_absolute);
int rc = ffrt_cond_timedwait(&cond_, &mutex->mutex_, &abs_time);
if (rc != 0) {
if (rc == ETIMEDOUT) {
// interrupted
return true;
}
}
FATAL_IF_ERROR("ffrt_cond_timedwait", rc);
return false;
}
protected:
struct timespec ConvertTime(uint64_t ms, uint64_t ns, bool is_absolute)
{
struct timespec abs_time = {0, 0};
if (!is_absolute) {
clock_gettime(CLOCK_REALTIME, &abs_time);
}
const int64_t MILLISECONDS_PER_SEC = 1000;
const int64_t NANOSECONDS_PER_MILLISEC = 1000000;
const int64_t NANOSECONDS_PER_SEC = 1000000000;
time_t seconds = ms / MILLISECONDS_PER_SEC;
time_t nanoseconds = (ms % MILLISECONDS_PER_SEC) * NANOSECONDS_PER_MILLISEC + ns;
abs_time.tv_sec += seconds;
abs_time.tv_nsec += nanoseconds;
if (abs_time.tv_nsec >= NANOSECONDS_PER_SEC) {
abs_time.tv_nsec -= NANOSECONDS_PER_SEC;
abs_time.tv_sec++;
}
return abs_time;
}
private:
ffrt_cond_t cond_;
};
class FFRTLockHolder {
public:
explicit FFRTLockHolder(FFRTMutex &mtx) : lock_(mtx)
{
lock_.Lock();
}
~FFRTLockHolder()
{
lock_.Unlock();
}
private:
FFRTMutex &lock_;
NO_COPY_SEMANTIC(FFRTLockHolder);
NO_MOVE_SEMANTIC(FFRTLockHolder);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_PLATFORM_FFRT_MUTEX_H

View File

@ -134,7 +134,11 @@ void Runtime::DestroyIfLastVm()
void Runtime::RegisterThread(JSThread* newThread)
{
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(threadsLock_);
#else
LockHolder lock(threadsLock_);
#endif
ASSERT(std::find(threads_.begin(), threads_.end(), newThread) == threads_.end());
threads_.emplace_back(newThread);
// send all current suspended requests to the new thread
@ -146,7 +150,11 @@ void Runtime::RegisterThread(JSThread* newThread)
// Note: currently only called when thread is to be destroyed.
void Runtime::UnregisterThread(JSThread* thread)
{
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(threadsLock_);
#else
LockHolder lock(threadsLock_);
#endif
ASSERT(std::find(threads_.begin(), threads_.end(), thread) != threads_.end());
ASSERT(!thread->IsInRunningState());
threads_.remove(thread);
@ -179,7 +187,11 @@ void Runtime::SuspendAllThreadsImpl(JSThread *current)
SuspendBarrier barrier;
for (uint32_t iterCount = 1U;; ++iterCount) {
{
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(threadsLock_);
#else
LockHolder lock(threadsLock_);
#endif
if (suspendNewCount_ == 0) {
suspendNewCount_++;
if (threads_.size() == 1) {
@ -218,7 +230,11 @@ void Runtime::SuspendAllThreadsImpl(JSThread *current)
}
}
if (iterCount < MAX_SUSPEND_RETRIES) {
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(threadsLock_);
#else
LockHolder lock(threadsLock_);
#endif
if (suspendNewCount_ != 0) {
// Someone has already suspended all threads.
// Wait until it finishes.
@ -234,7 +250,11 @@ void Runtime::SuspendAllThreadsImpl(JSThread *current)
void Runtime::ResumeAllThreadsImpl(JSThread *current)
{
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(threadsLock_);
#else
LockHolder lock(threadsLock_);
#endif
if (suspendNewCount_ > 0) {
suspendNewCount_--;
}

View File

@ -31,6 +31,10 @@
#include <list>
#include <memory>
#if defined(ENABLE_FFRT_INTERFACES)
#include "ecmascript/platform/ffrt_mutex.h"
#endif
namespace panda::ecmascript {
class Runtime {
public:
@ -65,7 +69,11 @@ public:
template<class Callback>
void GCIterateThreadList(const Callback &cb)
{
#if defined(ENABLE_FFRT_INTERFACES)
FFRTLockHolder lock(threadsLock_);
#else
LockHolder lock(threadsLock_);
#endif
GCIterateThreadListWithoutLock(cb);
}
@ -263,8 +271,13 @@ private:
return sharedNativePointerCallbacks_;
}
#if defined(ENABLE_FFRT_INTERFACES)
FFRTMutex threadsLock_;
FFRTConditionVariable threadSuspendCondVar_;
#else
Mutex threadsLock_;
ConditionVariable threadSuspendCondVar_;
#endif
Mutex serializeLock_;
std::list<JSThread*> threads_;
uint32_t suspendNewCount_ {0};