mirror of https://github.com/alibaba/MNN.git
Compare commits
7 Commits
aedc50894e
...
3c7914676c
Author | SHA1 | Date |
---|---|---|
|
3c7914676c | |
|
fa3b2161a9 | |
|
2a750ad7f8 | |
|
ad83430bf8 | |
|
0f1376f015 | |
|
3db5a478ed | |
|
c0bd7bac72 |
|
@ -0,0 +1,14 @@
|
|||
# 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.
|
||||
|
||||
docs/
|
|
@ -0,0 +1,73 @@
|
|||
# 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.
|
||||
|
||||
# yaml-language-server: $schema=https://huacnlee.github.io/autocorrect/schema.json
|
||||
rules:
|
||||
# Auto add spacing between CJK (Chinese, Japanese, Korean) and English words.
|
||||
# 0 - off, 1 - error, 2 - warning
|
||||
space-word: 1
|
||||
# Add space between some punctuations.
|
||||
space-punctuation: 1
|
||||
# Add space between brackets (), [] when near the CJK.
|
||||
space-bracket: 1
|
||||
# Add space between ``, when near the CJK.
|
||||
space-backticks: 1
|
||||
# Add space between dash `-`
|
||||
space-dash: 1
|
||||
# Convert to fullwidth.
|
||||
fullwidth: 1
|
||||
# To remove space near the fullwidth punctuations.
|
||||
no-space-fullwidth: 1
|
||||
# To remove space arouned the fullwidth quotes “”, ''.
|
||||
no-space-fullwidth-quote: 1
|
||||
# Fullwidth alphanumeric characters to halfwidth.
|
||||
halfwidth-word: 1
|
||||
# Fullwidth punctuations to halfwidth in english.
|
||||
halfwidth-punctuation: 1
|
||||
# Spellcheck
|
||||
spellcheck: 0
|
||||
# Enable or disable in spatial context
|
||||
context:
|
||||
# Enable or disable to format codeblock in Markdown or AsciiDoc etc.
|
||||
codeblock: 1
|
||||
textRules:
|
||||
# No default text rules.
|
||||
spellcheck:
|
||||
words:
|
||||
# Please do not add a general English word (eg. apple, python) here.
|
||||
# Users can add their special words to their .autocorrectrc file by their need.
|
||||
fileTypes:
|
||||
# ext: grammar_name
|
||||
# YAML
|
||||
yaml: yaml
|
||||
yml: yaml
|
||||
# JSON
|
||||
json: json
|
||||
json5: json
|
||||
# Markdown
|
||||
markdown: markdown
|
||||
md: markdown
|
||||
mdx: markdown
|
||||
# C / C++
|
||||
cc: c
|
||||
cpp: c
|
||||
c: c
|
||||
# XML
|
||||
xml: xml
|
||||
# Shell
|
||||
sh: ruby
|
||||
shell: ruby
|
||||
# Text
|
||||
text: text
|
||||
plain: text
|
||||
txt: text
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 120
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
DerivePointerAlignment: false
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseBlocks: true
|
||||
PackConstructorInitializers: CurrentLine
|
||||
SpacesBeforeTrailingComments: 1
|
||||
---
|
|
@ -0,0 +1,8 @@
|
|||
#ignore files
|
||||
.vscode
|
||||
ffrt.cfg
|
||||
build
|
||||
test/build
|
||||
benchmarks/output
|
||||
output
|
||||
trace.json
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"MD013": false,
|
||||
"MD024": {
|
||||
"siblings_only": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# Benchmarks
|
||||
|
||||
## 测试场景
|
||||
|
||||
1. `fork_join`:通过构造 fork/join 执行时间,模拟线程创建和堵塞场景;
|
||||
2. `fib`:通过构造斐波那契序列,模拟嵌套调用场景;
|
||||
3. `face_story`:通过构造人脸数据,模拟人脸检测场景;
|
||||
|
||||
## 测试方法
|
||||
|
||||
```shell
|
||||
cd benchmarks
|
||||
./benchmarks count # count 表明执行次数
|
||||
```
|
||||
|
||||
## 测试结果
|
||||
|
||||
1. 测试数据和分析归档到 `benchmarks/output/tag_${stamp}/benchmark_${stamp}.svg`,其中 `stamp` 是最近一次 commit 提交时间
|
||||
2. 测试结果已取平均
|
|
@ -0,0 +1,266 @@
|
|||
# Copyright (c) 2023 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.
|
||||
import("//build/ohos.gni")
|
||||
import("ffrt.gni")
|
||||
|
||||
defines = []
|
||||
|
||||
config("ffrt_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"interfaces/kits",
|
||||
"interfaces/inner_api"
|
||||
]
|
||||
|
||||
ffrt_defaults_cflags = [
|
||||
"-fstack-protector-all",
|
||||
"-Wno-unused-variable",
|
||||
"-Wno-unused-function",
|
||||
"-Wno-unused-value",
|
||||
"-Wno-unused-private-field",
|
||||
"-Wno-tautological-constant-out-of-range-compare",
|
||||
"-Wno-shadow",
|
||||
"-Wno-float-equal",
|
||||
"-Wno-unused-parameter",
|
||||
"-fno-common",
|
||||
]
|
||||
|
||||
cflags = ffrt_defaults_cflags
|
||||
cflags_c = [
|
||||
"-fstack-protector-all",
|
||||
"-fno-common",
|
||||
]
|
||||
cflags_cc = ffrt_defaults_cflags
|
||||
|
||||
ffrt_debug_defines = [
|
||||
"FFRT_LOG_LEVEL=3",
|
||||
"FFRT_BBOX_ENABLE",
|
||||
"FFRT_OH_EVENT_RECORD",
|
||||
"FFRT_CO_BACKTRACE_OH_ENABLE",
|
||||
"FFRT_OH_TRACE_ENABLE",
|
||||
"FFRT_TRACE_LEVEL=1",
|
||||
"FFRT_TRACE_RECORD_LEVEL=1",
|
||||
"FFRT_SEND_EVENT",
|
||||
"FFRT_ALLOCATOR_MMAP_SIZE=${ffrt_allocator_mmap_size}",
|
||||
"FFRT_STACK_SIZE=${ffrt_stack_size}",
|
||||
]
|
||||
|
||||
#ffrt_release_defines = [
|
||||
# "FFRT_LOG_LEVEL=0",
|
||||
# "FFRT_RELEASE",
|
||||
#]
|
||||
|
||||
defines += ffrt_debug_defines
|
||||
|
||||
if (is_asan && !use_hwasan) {
|
||||
defines += [ "ASAN_MODE" ]
|
||||
}
|
||||
|
||||
if (use_hwasan || is_tsan) {
|
||||
defines += [ "CLOSE_COROUTINE_MODE" ]
|
||||
}
|
||||
|
||||
if (target_cpu == "arm") {
|
||||
defines += [ "APP_USE_ARM" ]
|
||||
}
|
||||
|
||||
if (is_ohos && !ffrt_task_local_enable) {
|
||||
defines += [ "FFRT_TASK_LOCAL_ENABLE" ]
|
||||
}
|
||||
|
||||
#build_variant is root/user, default user
|
||||
if (build_variant == "root") {
|
||||
defines += [ "FFRT_ENG_DEBUG" ]
|
||||
}
|
||||
|
||||
#defines += ffrt_release_defines
|
||||
}
|
||||
|
||||
config("ffrt_inner_config") {
|
||||
include_dirs = [
|
||||
"include",
|
||||
"src",
|
||||
"src/dfx/log",
|
||||
"src_ext",
|
||||
"src/sched",
|
||||
]
|
||||
|
||||
if (is_ohos && is_clang && (target_cpu == "arm" || target_cpu == "arm64")) {
|
||||
cflags = [
|
||||
"-flto=thin",
|
||||
"-fsplit-lto-unit",
|
||||
]
|
||||
}
|
||||
|
||||
ffrt_inner_cflags = [
|
||||
"-std=c++17",
|
||||
"-g",
|
||||
"-D_FORTIFY_SOURCE=2",
|
||||
"-O2",
|
||||
"-fPIC",
|
||||
"-DFFRT_PTHREAD_ENABLE",
|
||||
"-DFFRT_OH_WATCHDOG_ENABLE",
|
||||
"-DQOS_WORKER_FRAME_RTG",
|
||||
"-DUSE_OHOS_QOS",
|
||||
"-DOHOS_STANDARD_SYSTEM",
|
||||
"-DTASKSTAT_LOG_ENABLE=0",
|
||||
]
|
||||
|
||||
cflags_cc = ffrt_inner_cflags
|
||||
}
|
||||
|
||||
ohos_shared_library("libffrt") {
|
||||
if (ffrt_support_enable) {
|
||||
branch_protector_ret = "pac_ret"
|
||||
public_configs = [ ":ffrt_config" ]
|
||||
configs = [ ":ffrt_inner_config" ]
|
||||
ldflags = [ "-Wl,-z,nodelete" ]
|
||||
|
||||
sources = [
|
||||
"src/core/entity.cpp",
|
||||
"src/core/task.cpp",
|
||||
"src/core/task_io.cpp",
|
||||
"src/core/version_ctx.cpp",
|
||||
"src/dfx/bbox/bbox.cpp",
|
||||
"src/dfx/bbox/fault_logger_fd_manager.cpp",
|
||||
"src/dfx/dump/dump.cpp",
|
||||
"src/dfx/log/ffrt_log.cpp",
|
||||
"src/dfx/sysevent/sysevent.cpp",
|
||||
"src/dfx/trace/ffrt_trace.cpp",
|
||||
"src/dfx/trace/ffrt_trace_chain.cpp",
|
||||
"src/dfx/trace_record/ffrt_trace_record.cpp",
|
||||
"src/dfx/watchdog/watchdog_util.cpp",
|
||||
"src/dm/dependence_manager.cpp",
|
||||
"src/dm/sdependence_manager.cpp",
|
||||
"src/eu/co2_context.c",
|
||||
"src/eu/co_routine.cpp",
|
||||
"src/eu/co_routine_factory.cpp",
|
||||
"src/eu/cpu_worker.cpp",
|
||||
"src/eu/execute_unit.cpp",
|
||||
"src/eu/io_poller.cpp",
|
||||
"src/eu/loop.cpp",
|
||||
"src/eu/loop_api.cpp",
|
||||
"src/eu/osattr_manager.cpp",
|
||||
"src/eu/qos_convert.cpp",
|
||||
"src/eu/qos_interface.cpp",
|
||||
"src/eu/rtg_ioctl.cpp",
|
||||
"src/eu/rtg_perf_ctrl.cpp",
|
||||
"src/eu/sexecute_unit.cpp",
|
||||
"src/eu/worker_thread.cpp",
|
||||
"src/ipc/ipc.cpp",
|
||||
"src/queue/base_queue.cpp",
|
||||
"src/queue/concurrent_queue.cpp",
|
||||
"src/queue/eventhandler_adapter_queue.cpp",
|
||||
"src/queue/eventhandler_interactive_queue.cpp",
|
||||
"src/queue/queue_api.cpp",
|
||||
"src/queue/queue_handler.cpp",
|
||||
"src/queue/queue_monitor.cpp",
|
||||
"src/queue/serial_queue.cpp",
|
||||
"src/queue/traffic_record.cpp",
|
||||
"src/sched/deadline.cpp",
|
||||
"src/sched/execute_ctx.cpp",
|
||||
"src/sched/frame_interval.cpp",
|
||||
"src/sched/interval.cpp",
|
||||
"src/sched/load_tracking.cpp",
|
||||
"src/sched/multi_workgroup.cpp",
|
||||
"src/sched/qos.cpp",
|
||||
"src/sched/sched_deadline.cpp",
|
||||
"src/sched/scheduler.cpp",
|
||||
"src/sched/stask_scheduler.cpp",
|
||||
"src/sched/task_scheduler.cpp",
|
||||
"src/sync/condition_variable.cpp",
|
||||
"src/sync/delayed_worker.cpp",
|
||||
"src/sync/timer_manager.cpp",
|
||||
"src/sync/mutex.cpp",
|
||||
"src/sync/perf_counter.cpp",
|
||||
"src/sync/poller.cpp",
|
||||
"src/sync/poller_api.cpp",
|
||||
"src/sync/record_mutex.cpp",
|
||||
"src/sync/shared_mutex.cpp",
|
||||
"src/sync/sleep.cpp",
|
||||
"src/sync/sync.cpp",
|
||||
"src/sync/thread.cpp",
|
||||
"src/sync/timer_api.cpp",
|
||||
"src/sync/wait_queue.cpp",
|
||||
"src/tm/cpu_task.cpp",
|
||||
"src/tm/io_task.cpp",
|
||||
"src/tm/queue_task.cpp",
|
||||
"src/tm/scpu_task.cpp",
|
||||
"src/tm/task_base.cpp",
|
||||
"src/tm/task_factory.cpp",
|
||||
"src/tm/uv_task.cpp",
|
||||
"src/util/cpu_boost_wrapper.cpp",
|
||||
"src/util/ffrt_cpu_boost.cpp",
|
||||
"src/util/ffrt_facade.cpp",
|
||||
"src/util/graph_check.cpp",
|
||||
"src/util/init.cpp",
|
||||
"src/util/spmc_queue.cpp",
|
||||
"src/util/time_format.cpp",
|
||||
"src/util/worker_monitor.cpp",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"bounds_checking_function:libsec_shared",
|
||||
"c_utils:utils",
|
||||
"faultloggerd:libbacktrace_local",
|
||||
"faultloggerd:libdfx_dumpcatcher",
|
||||
"faultloggerd:libfaultloggerd",
|
||||
"faultloggerd:libunwinder",
|
||||
"hilog:libhilog",
|
||||
"hisysevent:libhisysevent",
|
||||
]
|
||||
|
||||
defines = []
|
||||
|
||||
if (ffrt_async_stack_enable) {
|
||||
defines += [ "FFRT_ASYNC_STACKTRACE" ]
|
||||
sources += [ "src/dfx/async_stack/ffrt_async_stack.cpp" ]
|
||||
}
|
||||
|
||||
defines += [ "FFRT_ENABLE_HITRACE_CHAIN" ]
|
||||
|
||||
output_extension = "so"
|
||||
symlink_target_name = [ "libffrt.z.so" ]
|
||||
part_name = "ffrt"
|
||||
subsystem_name = "resourceschedule"
|
||||
install_images = [
|
||||
"system",
|
||||
"updater",
|
||||
]
|
||||
innerapi_tags = [
|
||||
"chipsetsdk_sp",
|
||||
"ndk",
|
||||
"sasdk",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("whitelist_cfg") {
|
||||
relative_install_dir = "ffrt"
|
||||
source = "ffrt_whitelist.conf"
|
||||
part_name = "ffrt"
|
||||
subsystem_name = "resourceschedule"
|
||||
install_enable = true
|
||||
install_images = [
|
||||
"system",
|
||||
"updater",
|
||||
]
|
||||
}
|
||||
|
||||
group("ffrt_ndk") {
|
||||
deps = [
|
||||
":libffrt",
|
||||
":whitelist_cfg",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
# 编译构建
|
||||
|
||||
## 构建依赖
|
||||
|
||||
因为当前 FFRT 编译依赖三方安全库(参见:[third_party_bounds_checking_function](https://gitee.com/openharmony/third_party_bounds_checking_function))的功能,当进行 linux 构建时,需要把三方安全库的代码一并下载到本地,放置目录如下
|
||||
|
||||
```plain
|
||||
├── resourceschedule_ffrt
|
||||
├── third_party
|
||||
└── bounds_checking_function
|
||||
```
|
||||
|
||||
## 构建参数
|
||||
|
||||
常见的构建宏定义说明
|
||||
|
||||
| 构建宏 | 含义 |
|
||||
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| FFRT_EXAMPLE | 在 CMakeList 中用于控制是否编译 ffrt examples |
|
||||
| FFRT_BENCHMARKS | 在 CMakeList 中用于控制是否编译 ffrt benchmarks |
|
||||
| FFRT_TEST_ENABLE | 在 CMakeList 中用于控制是否编译 ffrt unittest cases |
|
||||
| FFRT_CLANG_COMPILE | 在 CMakeList 中用于控制是否使用 clang 编译 |
|
||||
| FFRT_SANITIZE | 在 CMakeList 中用于控制是否开启 sanitizer 检测 |
|
||||
| FFRT_BBOX_ENABLE | 在 CMakeList 中用于控制是否开启 FFRT 黑匣子,用于记录发生 crash 时 FFRT 线程、协程的状态 |
|
||||
| FFRT_LOG_LEVEL | 在 CMakeList&BUILD.gn 中用于动态设置 FFRT 默认日志级别,支持 0-3,依次为 ERROR,WARN,INFO,DEBUG,例如需要打开 DEBUG 及以上级别的日志,设置 `FFRT_LOG_LEVEL=3` |
|
||||
|
||||
## Linux 构建
|
||||
|
||||
### 编译环境
|
||||
|
||||
编译的 Linux 环境需要已安装 CMake(版本 3.10 以上)以及编译器 GCC 或 Clang
|
||||
|
||||
### 编译脚本
|
||||
|
||||
ffrt 代码根目录下的 CMakeList
|
||||
|
||||
### 编译命令
|
||||
|
||||
使用 CMake 编译:
|
||||
|
||||
```shell
|
||||
mkdir -p build
|
||||
cd build && cmake .. -DFFRT_EXAMPLE=ON
|
||||
cmake --build . -j # add `-j` for parallel compilation
|
||||
./examples/ffrt_submit # run some ffrt examples
|
||||
```
|
||||
|
||||
或者直接使用代码仓中的 shell 脚本:
|
||||
|
||||
```shell
|
||||
sh scripts/run_example.sh
|
||||
```
|
||||
|
||||
### 编译产物
|
||||
|
||||
FFRT 样例的可执行文件 ffrt_submit
|
||||
|
||||
```plain
|
||||
├── resourceschedule_ffrt
|
||||
└── build
|
||||
└──examples
|
||||
└──ffrt_submit
|
||||
```
|
||||
|
||||
FFRT 动态库文件 libffrt.so
|
||||
|
||||
```plain
|
||||
├── resourceschedule_ffrt
|
||||
└── build
|
||||
└──src
|
||||
└──libffrt.so
|
||||
```
|
||||
|
||||
## OpenHarmony 构建
|
||||
|
||||
### 编译环境
|
||||
|
||||
编译环境部署参考 OpenHarmony 社区官方文档:[编译构建指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-build-all.md)
|
||||
|
||||
### 编译脚本
|
||||
|
||||
ffrt 代码根目录下的 BUILD.gn
|
||||
|
||||
### 编译命令
|
||||
|
||||
在官方提供的产品编译命令中指定编译 FFRT 模块,仅需将 build-target 参数设置成 ffrt
|
||||
|
||||
以 rk3568 产品为例,进入源码根目录,执行:
|
||||
|
||||
64 位
|
||||
|
||||
```shell
|
||||
./build.sh --product-name rk3568 --target-cpu arm64 --ccache --build-target ffrt
|
||||
```
|
||||
|
||||
32 位
|
||||
|
||||
```shell
|
||||
./build.sh --product-name rk3568 --ccache --build-target ffrt
|
||||
```
|
||||
|
||||
### 开发依赖
|
||||
|
||||
```json
|
||||
external_deps = [
|
||||
"ffrt:libffrt",
|
||||
]
|
||||
```
|
|
@ -0,0 +1,114 @@
|
|||
# -------------------------------------------------------------------
|
||||
# ffrt CMake
|
||||
#
|
||||
# To enable thread sanitizer:
|
||||
# -DCMAKE_CXX_FLAGS="-fsanitize=thread -g"
|
||||
#
|
||||
# To enable address and leak sanitizers
|
||||
# -DCMAKE_CXX_FLAGS="-fsanitize=address -fsanitize=leak -g"
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# CMake version
|
||||
cmake_minimum_required (VERSION 3.10)
|
||||
|
||||
# build options
|
||||
option(FFRT_BBOX_ENABLE "Enables ffrt black box" ON)
|
||||
option(FFRT_EXAMPLE "Enables ffrt examples compile" OFF)
|
||||
option(FFRT_BENCHMARKS "Enables ffrt Benchmarks" OFF)
|
||||
option(FFRT_TEST_ENABLE "Enables ffrt test" OFF)
|
||||
option(FFRT_CLANG_COMPILE "use clang/clang++ for compiling" OFF)
|
||||
option(FFRT_SANITIZE "enable address or thread sanitizer" OFF)
|
||||
|
||||
project(ffrt LANGUAGES C CXX ASM)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
|
||||
#cmake build type settings,release or debug
|
||||
if(CMAKE_BUILD_TYPE STREQUAL Release)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFFRT_RELEASE -DFFRT_LOG_LEVEL=0")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFFRT_LOG_LEVEL=3")
|
||||
endif()
|
||||
|
||||
# project-specific variables
|
||||
set(FFRT_CODE_PATH ${PROJECT_SOURCE_DIR}/src)
|
||||
set(FFRT_INNER_INCLUDE_PATH ${PROJECT_SOURCE_DIR}/include)
|
||||
set(FFRT_INNER_API_PATH ${PROJECT_SOURCE_DIR}/interfaces/inner_api)
|
||||
set(FFRT_API_PATH ${PROJECT_SOURCE_DIR}/interfaces/kits)
|
||||
set(FFRT_BUILD_PATH ${PROJECT_SOURCE_DIR}/build)
|
||||
set(ROOT_PATH ${PROJECT_SOURCE_DIR}/../)
|
||||
set(SECUREC_PATH ${PROJECT_SOURCE_DIR}/third_party/bounds_checking_function CACHE PATH
|
||||
"Path to securec")
|
||||
set(TRACE_PATH ${FFRT_CODE_PATH}/dfx/trace)
|
||||
set(QOS_PATH ${FFRT_CODE_PATH}/sched/)
|
||||
set(securec_includes ${SECUREC_PATH}/include)
|
||||
aux_source_directory(${SECUREC_PATH}/src securec_srcs)
|
||||
add_library(securec SHARED ${securec_srcs})
|
||||
target_include_directories(securec PRIVATE ${securec_includes})
|
||||
include_directories(${securec_includes})
|
||||
|
||||
#compiler flags
|
||||
if(FFRT_SANITIZE STREQUAL address)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-recover=address,all -fno-omit-frame-pointer -DASAN_MODE")
|
||||
elseif(FFRT_SANITIZE STREQUAL thread)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer -DTSAN_MODE -DCLOSE_COROUTINE_MODE")
|
||||
endif()
|
||||
|
||||
if(FFRT_UT_ENABLE STREQUAL OFF AND FFRT_ST_ENABLE STREQUAL OFF)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE STREQUAL Release)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -g -O2 -fPIC")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -g -O0 -fPIC")
|
||||
endif()
|
||||
|
||||
# add the binary tree to the search path for include files
|
||||
include_directories(${FFRT_API_PATH})
|
||||
include_directories(${FFRT_INNER_API_PATH})
|
||||
include_directories(${FFRT_INNER_INCLUDE_PATH})
|
||||
include_directories(${FFRT_CODE_PATH})
|
||||
include_directories(${TRACE_PATH})
|
||||
include_directories(${QOS_PATH})
|
||||
|
||||
message(STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE})
|
||||
message(STATUS "FFRT_BBOX_ENABLE: " ${FFRT_BBOX_ENABLE})
|
||||
message(STATUS "FFRT_EXAMPLE: " ${FFRT_EXAMPLE})
|
||||
message(STATUS "FFRT_BENCHMARKS: " ${FFRT_BENCHMARKS})
|
||||
message(STATUS "FFRT_TEST_ENABLE: " ${FFRT_TEST_ENABLE})
|
||||
message(STATUS "FFRT_CLANG_COMPILE: " ${FFRT_CLANG_COMPILE})
|
||||
message(STATUS "FFRT_SANITIZE: " ${FFRT_SANITIZE})
|
||||
|
||||
add_definitions("-DFFRT_PTHREAD_ENABLE")
|
||||
add_definitions("-DFFRT_ENABLE_TRAFFIC_MONITOR")
|
||||
|
||||
# ffrt qos
|
||||
add_definitions(-DUSE_OHOS_QOS)
|
||||
|
||||
# ffrt BBOX
|
||||
if(FFRT_BBOX_ENABLE STREQUAL ON)
|
||||
add_definitions("-DFFRT_BBOX_ENABLE")
|
||||
endif()
|
||||
|
||||
# ffrt trace record level
|
||||
add_definitions("-DFFRT_TRACE_RECORD_LEVEL=1")
|
||||
|
||||
# libffrt.so
|
||||
add_subdirectory(src)
|
||||
LINK_DIRECTORIES(${FFRT_BUILD_PATH}/src)
|
||||
|
||||
# ffrt Examples
|
||||
if(FFRT_EXAMPLE STREQUAL ON)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# ffrt Benchmarks
|
||||
if(FFRT_BENCHMARKS STREQUAL ON)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
|
||||
# ffrt unit tests
|
||||
if(FFRT_TEST_ENABLE STREQUAL ON)
|
||||
add_subdirectory(test)
|
||||
endif()
|
|
@ -0,0 +1,69 @@
|
|||
# Contributing Guidelines
|
||||
|
||||
## Contribute
|
||||
|
||||
We welcome contributions from the community! By contributing, you can help improve FFRT and make it more robust.
|
||||
|
||||
Here are some ways you can contribute:
|
||||
|
||||
1. Report Issues:
|
||||
|
||||
- If you encounter any bugs or have suggestions for improvements, please open an issue on this repository. Provide detailed information to help us understand and resolve the issue.
|
||||
|
||||
2. Submit Pull Requests:
|
||||
|
||||
- If you have made improvements to the code, feel free to submit a pull request. Ensure that your code adheres to the projects's coding standards and is well-documented.
|
||||
- Please ensure that your code follows the project's coding standards. We use `.clang-format` to maintain consistent code style. Run the following command to format your code before committing:
|
||||
|
||||
```shell
|
||||
clang-format -i file
|
||||
```
|
||||
|
||||
- To ensure documentation quality, we use:
|
||||
|
||||
- `cspell.json` for spell checking. Run the following command to check for spelling errors:
|
||||
|
||||
```shell
|
||||
cspell "src/**/*.cpp" "docs/**/*.md"
|
||||
```
|
||||
|
||||
- `.markdownlint.json` for Markdown file format standards. Run the following commands to lint your Markdown files:
|
||||
|
||||
```shell
|
||||
markdownlint "**/*.md"
|
||||
```
|
||||
|
||||
- `.autocorrectrc` and `.autocorrectignore` for ensuring proper formatting of mixed Chinese and English content. Run the following commands to autocorrect documentation:
|
||||
|
||||
```shell
|
||||
autocorrect "**/*.md"
|
||||
```
|
||||
|
||||
- We also recommend using the following VSCode plugins to help adhere to coding and documentation standards:
|
||||
|
||||
- [Clang-Format](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) or [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) for maintaining consistent code style.
|
||||
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) for spell checking
|
||||
- [markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) for Markdown file format linting.
|
||||
- [AutoCorrect](https://marketplace.visualstudio.com/items?itemName=huacnlee.autocorrect) for auto-correcting mixed Chinese and English content.
|
||||
|
||||
3. Write Tests:
|
||||
|
||||
- To maintain the quality of the project, we encourage you to write tests for new features and bug fixes. This helps ensure that the codebase remains stable and reliable.
|
||||
|
||||
4. Improve Documentation:
|
||||
|
||||
- Good documentation is key to a successful project. If you find areas in the documentation that can be improved, please contribute by updating the `README.md` or other documentation files.
|
||||
|
||||
5. Review Pull Requests:
|
||||
|
||||
- Reviewing and providing feedback on other contributor's pull requests is a valuable way to contribute. Your insights can help maintain the quality and consistency of the project.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
By participating in this project, you agree to abide by our [Code of Conduct](https://developer.huawei.com/consumer/en/devservice/guidelines/). Please read it to understand the standards and expectations for contributing.
|
||||
|
||||
## Get in Touch
|
||||
|
||||
If you have any questions or need further guidance, feel free to reach us via [email](mailto:hiffrt@huawei.com) or join our [Q&A community](https://developer.huawei.com/consumer/cn/forum/).
|
||||
|
||||
Thank you for your contributions and support!
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (c) 2021 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.
|
||||
|
||||
This is the configuration file template for OpenHarmony OSS Audit Tool, please copy it to your project root dir and modify it refer to OpenHarmony/tools_oat/README.
|
||||
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<oatconfig>
|
||||
<licensefile></licensefile>
|
||||
<filefilterlist>
|
||||
<filefilter name="defaultFilter" desc="Files not to check">
|
||||
<filteritem type="filepath" name="docs/figures/.*.png" desc="images in user guide"/>
|
||||
<filteritem type="filepath" name="benchmarks/base.csv" desc="benchmarks result xml file"/>
|
||||
<filteritem type="filepath" name="benchmarks/speedup/base.csv" desc="benchmarks speedup result xml file"/>
|
||||
<filteritem type="filepath" name="benchmarks/serial_sched_time/base.csv" desc="benchmarks serial_sched_time result xml file"/>
|
||||
</filefilter>
|
||||
</filefilterlist>
|
||||
</oatconfig>
|
||||
</configuration>
|
|
@ -0,0 +1,69 @@
|
|||
# 并发编程框架 FFRT
|
||||
|
||||
- [并发编程框架 FFRT](#并发编程框架-ffrt)
|
||||
- [简介](#简介)
|
||||
- [目录](#目录)
|
||||
- [编译构建](#编译构建)
|
||||
- [Testing](#testing)
|
||||
- [Benchmarks](#benchmarks)
|
||||
- [Release](#release)
|
||||
- [Contributing Code](#contributing-code)
|
||||
|
||||
## 简介
|
||||
|
||||
FFRT: Function Flow Runtime,一种并发编程框架,提供以数据依赖的方式构建异步并发任务的能力,包括数据依赖管理、任务执行器、系统事件处理等。并采用基于协程的任务执行方式,可以提高任务并行度、提升线程利用率、降低系统线程总数;充分利用多核平台的计算资源,保证系统对所有资源的集约化管理。最终解决系统线程资源滥用问题,打造极致用户体验。
|
||||
|
||||
功能介绍详见:[FFRT 用户指南](docs/README.md)
|
||||
|
||||
## 目录
|
||||
|
||||
```plain
|
||||
├── benchmarks # 性能对比测试用例
|
||||
├── docs # 用户指南
|
||||
├── examples # 使用案例
|
||||
├── interfaces # 接口目录
|
||||
│ ├── inner_api # 内部接口
|
||||
│ └── kits # 对外接口
|
||||
│ ├── c
|
||||
│ └── cpp
|
||||
├── scripts
|
||||
├── src
|
||||
│ ├── core # 核心模块
|
||||
│ ├── dfx # 维测功能
|
||||
│ ├── dm # 依赖管理
|
||||
│ ├── eu # 执行单元
|
||||
│ ├── internal_inc # 对内接口目录
|
||||
│ ├── ipc
|
||||
│ ├── queue
|
||||
│ ├── sched
|
||||
│ ├── sync
|
||||
│ ├── tm
|
||||
│ └── util
|
||||
├── test
|
||||
└── tools
|
||||
└── ffrt_trace_process
|
||||
```
|
||||
|
||||
## 编译构建
|
||||
|
||||
For detailed instructions on building FFRT, see [BUILD.md](BUILD.md).
|
||||
|
||||
## Testing
|
||||
|
||||
For detailed instructions on testing FFRT, see [TESTING.md](TESTING.md).
|
||||
|
||||
## Benchmarks
|
||||
|
||||
To evaluate and verify the performance of FFRT, extensive benchmark tests were conducted. These tests utilized various datasets and real-world scenarios to ensure reliability and efficiency across different environments.
|
||||
|
||||
Detailed test results and analyses can be found in the `benchmarks` directory. We encourage community members to perform further tests based on their specific use cases and provide feedback to help us continuously improve FFRT.
|
||||
|
||||
For detailed instructions on conducting benchmark tests, see [BENCHMARKS.md](BENCHMARKS.md).
|
||||
|
||||
## Release
|
||||
|
||||
Please see the [Release](RELEASE.md) note for information about C and C++ API versions.
|
||||
|
||||
## Contributing Code
|
||||
|
||||
Please see the [Contributing](CONTRIBUTING.md) guide for information on how to contribute code.
|
|
@ -0,0 +1,6 @@
|
|||
# RELEASE-NOTES
|
||||
|
||||
## 1.0.0
|
||||
|
||||
1. FFRT means Function Flow Run Time. It is a runtime library for asynchronous task concurrency.
|
||||
2. Initial version provides these features: task management, mutex, condition variable and sleep/yield.
|
|
@ -0,0 +1,71 @@
|
|||
# Testing FFRT
|
||||
|
||||
## XTS
|
||||
|
||||
XTS 介绍详见 OpenHarmony 社区官方文档:[XTS 子系统](https://gitee.com/openharmony/xts_acts/blob/master/README_zh.md)
|
||||
|
||||
### 代码路径
|
||||
|
||||
已覆盖 FFRT 所有 API 开源接口,用例代码详见:[FFRT 用例](https://gitee.com/openharmony/xts_acts/tree/master/resourceschedule/resourceschedule_standard/ffrt)
|
||||
|
||||
**用例 Hap 名称**:`ActsFfrtNativeTest`
|
||||
|
||||
### 编译依赖
|
||||
|
||||
参考 OpenHarmony 社区官方文档:[编译构建指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-build-all.md)
|
||||
|
||||
### 编译命令
|
||||
|
||||
以 rk3568 产品为例,进入源码根目录,执行:
|
||||
|
||||
```shell
|
||||
./build.sh --product-name rk3568 system_size=standard target_subsystem=resourceschedule
|
||||
```
|
||||
|
||||
### 执行命令
|
||||
|
||||
```shell
|
||||
run -l ActsFfrtNativeTest
|
||||
```
|
||||
|
||||
## TDD
|
||||
|
||||
### 代码路径
|
||||
|
||||
```plain
|
||||
foundation/resourceschedule/ffrt/test/
|
||||
```
|
||||
|
||||
### 编译依赖
|
||||
|
||||
参考 OpenHarmony 社区官方文档:[编译构建指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-build-all.md)
|
||||
|
||||
### 编译命令
|
||||
|
||||
以 rk3568 产品为例,进入源码根目录,执行:
|
||||
|
||||
64 位
|
||||
|
||||
```shell
|
||||
./build.sh --product-name rk3568 --target-cpu arm64 --ccache --build-target foundation/resourceschedule/ffrt/test/ut:ffrt_unittest_ffrt
|
||||
```
|
||||
|
||||
32 位
|
||||
|
||||
```shell
|
||||
./build.sh --product-name rk3568 --ccache --build-target foundation/resourceschedule/ffrt/test/ut:ffrt_unittest_ffrt
|
||||
```
|
||||
|
||||
### 执行命令
|
||||
|
||||
```shell
|
||||
run -t ut -ss ffrttest
|
||||
```
|
||||
|
||||
### Running unit-tests via cmake/ctest
|
||||
|
||||
```shell
|
||||
cmake -S. -Bbuild -DFFRT_TEST_ENABLE=ON
|
||||
cmake --build build --target ffrt_ut
|
||||
ctest --test-dir build/test
|
||||
```
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"name": "@ohos/ffrt",
|
||||
"description": "Concurrent Programming Framework",
|
||||
"optional": "false",
|
||||
"version": "4.0",
|
||||
"license": "Apache License 2.0",
|
||||
"publishAs": "code-segment",
|
||||
"segment": {
|
||||
"destPath": "foundation/resourceschedule/ffrt"
|
||||
},
|
||||
"dirs": {},
|
||||
"scripts": {},
|
||||
"component": {
|
||||
"name": "ffrt",
|
||||
"subsystem": "resourceschedule",
|
||||
"syscap": [
|
||||
"SystemCapability.Resourceschedule.Ffrt.Core"
|
||||
],
|
||||
"features": [
|
||||
"ffrt_support_enable",
|
||||
"ffrt_allocator_mmap_size",
|
||||
"ffrt_stack_size"
|
||||
],
|
||||
"adapted_system_type": [
|
||||
"standard"
|
||||
],
|
||||
"hisysevent_config": [
|
||||
"//foundation/resourceschedule/ffrt/hisysevent.yaml"
|
||||
],
|
||||
"rom": "",
|
||||
"ram": "",
|
||||
"deps": {
|
||||
"components": [
|
||||
"bounds_checking_function",
|
||||
"c_utils",
|
||||
"hilog",
|
||||
"hisysevent",
|
||||
"faultloggerd",
|
||||
"napi"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"sub_component": [
|
||||
"//foundation/resourceschedule/ffrt:libffrt",
|
||||
"//foundation/resourceschedule/ffrt:ffrt_ndk"
|
||||
],
|
||||
"inner_kits": [
|
||||
{
|
||||
"header": {
|
||||
"header_base": "//foundation/resourceschedule/ffrt/interfaces/",
|
||||
"header_files": [
|
||||
"kits/ffrt.h",
|
||||
"kits/c/condition_variable.h",
|
||||
"kits/c/loop.h",
|
||||
"kits/c/mutex.h",
|
||||
"kits/c/shared_mutex.h",
|
||||
"kits/c/sleep.h",
|
||||
"kits/c/task.h",
|
||||
"kits/c/timer.h",
|
||||
"kits/c/type_def.h",
|
||||
"kits/cpp/condition_variable.h",
|
||||
"kits/cpp/mutex.h",
|
||||
"kits/cpp/shared_mutex.h",
|
||||
"kits/cpp/queue.h",
|
||||
"kits/cpp/sleep.h",
|
||||
"kits/cpp/task.h",
|
||||
|
||||
"inner_api/ffrt_inner.h",
|
||||
"inner_api/c/deadline.h",
|
||||
"inner_api/c/executor_task.h",
|
||||
"inner_api/c/ffrt_cpu_boost.h",
|
||||
"inner_api/c/ffrt_dump.h",
|
||||
"inner_api/c/ffrt_ipc.h",
|
||||
"inner_api/c/init.h",
|
||||
"inner_api/c/queue_ext.h",
|
||||
"inner_api/c/task_ext.h",
|
||||
"inner_api/c/thread.h",
|
||||
"inner_api/c/type_def_ext.h",
|
||||
"inner_api/cpp/deadline.h",
|
||||
"inner_api/cpp/future.h",
|
||||
"inner_api/cpp/qos_convert.h",
|
||||
"inner_api/cpp/task_ext.h",
|
||||
"inner_api/cpp/thread.h"
|
||||
]
|
||||
},
|
||||
"name": "//foundation/resourceschedule/ffrt:libffrt"
|
||||
}
|
||||
],
|
||||
"test": [
|
||||
"//foundation/resourceschedule/ffrt/test/ut:ffrt_unittest_ffrt"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"enabledFileTypes": {
|
||||
"*": false,
|
||||
"cpp": true,
|
||||
"markdown": true
|
||||
},
|
||||
"languageSettings": [
|
||||
{
|
||||
"languageId": "markdown",
|
||||
"dictionaries": [
|
||||
"cpp"
|
||||
],
|
||||
"ignoreRegExpList": [
|
||||
"/`(?:.)+?`/ig",
|
||||
"/\\[(?:.)+?\\]/ig",
|
||||
"/\\s+```(?:.|\\s)+?\\s+```/mig"
|
||||
]
|
||||
}
|
||||
],
|
||||
"words": [
|
||||
"resourceschedule",
|
||||
"ffrt",
|
||||
"libffrt"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2023-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.
|
||||
declare_args() {
|
||||
ffrt_support_enable = true
|
||||
ffrt_async_stack_enable = true
|
||||
ffrt_task_local_enable = false
|
||||
ffrt_allocator_mmap_size = "8 * 1024 * 1024"
|
||||
ffrt_stack_size = "1 << 20"
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
log_ctr {
|
||||
ffrt_ut
|
||||
foundation
|
||||
CameraDaemon
|
||||
com.ohos.sceneboard
|
||||
}
|
||||
|
||||
worker_monitor {
|
||||
updater
|
||||
hdcd
|
||||
}
|
||||
|
||||
SetThreadAttr {
|
||||
CameraDaemon
|
||||
}
|
||||
|
||||
CreateCPUWorker {
|
||||
CameraDaemon
|
||||
}
|
||||
|
||||
HandleTaskNotifyConservative {
|
||||
CameraDaemon
|
||||
}
|
||||
|
||||
HandleTaskNotifyUltraConservative {
|
||||
bluetooth
|
||||
}
|
||||
|
||||
IsDelayedWorkerPreserved {
|
||||
foundation
|
||||
com.ohos.sceneboard
|
||||
}
|
||||
|
||||
IsInSFFRTListOHOS {
|
||||
/system/bin/hilogd
|
||||
/system/bin/uitest
|
||||
heter_tuning_tool
|
||||
}
|
||||
|
||||
IsInSFFRTList{
|
||||
zygote
|
||||
}
|
||||
|
||||
WhiteListTest {
|
||||
./test/ut/ffrt_ut
|
||||
ut_whitelist
|
||||
./ut_whitelist
|
||||
ffrt_ut
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
# 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.
|
||||
|
||||
domain: FFRT
|
||||
|
||||
AI_KERN_POWER_UP_ERR:
|
||||
__BASE: {type: FAULT, level: MINOR, desc: AI KERNEL ipu powerup fail or status invalid, preserve: true}
|
||||
ERROR_LEVEL: {type: INT32, desc: error level}
|
||||
IC_NAME: {type: STRING, desc: IC name}
|
||||
MODULE_NAME: {type: STRING, desc: module name}
|
||||
DESCRIPTION: {type: STRING, desc: description}
|
||||
COUNT: {type: INT32, desc: report counts}
|
||||
CONTENT: {type: STRING, desc: fault message}
|
||||
DEVICE_NAME: {type: STRING, desc: device name}
|
||||
RUNNING_TEST_SWITCH: {type: BOOL, desc: running_test_switch}
|
||||
FAULT_PHENOMENON: {type: STRING, desc: fault_phenomenon}
|
||||
NFF_THRESHOLD_MONTH: {type: INT32, desc: nff_threshold_month}
|
||||
NFF_THRESHOLD_DAY: {type: INT32, desc: nff_threshold_day}
|
||||
|
||||
AI_KERN_WTD_TIMEOUT_ERR:
|
||||
__BASE: {type: FAULT, level: MINOR, desc: AI KERNEL ipu soft wtd timeout, preserve: true}
|
||||
ERROR_LEVEL: {type: INT32, desc: error level}
|
||||
IC_NAME: {type: STRING, desc: IC name}
|
||||
MODULE_NAME: {type: STRING, desc: module name}
|
||||
DESCRIPTION: {type: STRING, desc: description}
|
||||
COUNT: {type: INT32, desc: report counts}
|
||||
CONTENT: {type: STRING, desc: fault message}
|
||||
DEVICE_NAME: {type: STRING, desc: device name}
|
||||
RUNNING_TEST_SWITCH: {type: BOOL, desc: running_test_switch}
|
||||
FAULT_PHENOMENON: {type: STRING, desc: fault_phenomenon}
|
||||
NFF_THRESHOLD_MONTH: {type: INT32, desc: nff_threshold_month}
|
||||
NFF_THRESHOLD_DAY: {type: INT32, desc: nff_threshold_day}
|
||||
|
||||
TASK_TIMEOUT:
|
||||
__BASE: {type: FAULT, level: CRITICAL, desc: task timeout, preserve: true}
|
||||
SENARIO: {type: STRING, desc: senario}
|
||||
PROCESS_NAME: {type: STRING, desc: process name}
|
||||
MSG: {type: STRING, desc: message}
|
||||
|
||||
QUEUE_OVERFLOW:
|
||||
__BASE: {type: FAULT, level: CRITICAL, desc: queue overflow, preserve: true}
|
||||
SENARIO: {type: STRING, desc: senario}
|
||||
PROCESS_NAME: {type: STRING, desc: process name}
|
||||
MSG: {type: STRING, desc: message}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_ENTITY_HPP
|
||||
#define FFRT_ENTITY_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
|
||||
#include "sync/sync.h"
|
||||
#include "tm/cpu_task.h"
|
||||
|
||||
namespace ffrt {
|
||||
struct VersionCtx;
|
||||
|
||||
struct Entity {
|
||||
static inline Entity* Instance()
|
||||
{
|
||||
static Entity ins;
|
||||
return &ins;
|
||||
}
|
||||
|
||||
VersionCtx* VA2Ctx(const void* p, SCPUEUTask* task);
|
||||
void RecycleVersion();
|
||||
|
||||
std::list<VersionCtx*> versionTrashcan; // VersionCtx to be deleted
|
||||
std::unordered_map<const void*, VersionCtx*> vaMap;
|
||||
/* It is only used to ensure the consistency between multiple groups of ctx,
|
||||
* and to ensure that the status cannot be changed between the query status and the do action
|
||||
*/
|
||||
fast_mutex criticalMutex_;
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 TASK_ATTR_PRIVATE_H
|
||||
#define TASK_ATTR_PRIVATE_H
|
||||
#include <string>
|
||||
#include "c/type_def_ext.h"
|
||||
#include "cpp/task_ext.h"
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
#include "eu/co_routine.h"
|
||||
|
||||
namespace ffrt {
|
||||
class task_attr_private {
|
||||
public:
|
||||
task_attr_private()
|
||||
: qos_(qos_default)
|
||||
{
|
||||
}
|
||||
|
||||
explicit task_attr_private(const task_attr attr)
|
||||
: qos_(attr.qos()),
|
||||
name_(attr.name()),
|
||||
delay_(attr.delay()),
|
||||
timeout_(attr.timeout()),
|
||||
prio_(attr.priority())
|
||||
{
|
||||
}
|
||||
|
||||
int qos_;
|
||||
std::string name_;
|
||||
uint64_t delay_ = 0;
|
||||
uint64_t timeout_ = 0;
|
||||
bool notifyWorker_ = true;
|
||||
bool isDelaying_ = false;
|
||||
ffrt_queue_priority_t prio_ = ffrt_queue_priority_low;
|
||||
bool taskLocal_ = false;
|
||||
bool headInsert_ = false;
|
||||
ffrt_function_header_t* timeoutCb_ = nullptr;
|
||||
uint64_t stackSize_ = STACK_SIZE;
|
||||
bool groupRoot_ = false;
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_VERSION_CTX_H
|
||||
#define FFRT_VERSION_CTX_H
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "internal_inc/types.h"
|
||||
#include "tm/scpu_task.h"
|
||||
namespace ffrt {
|
||||
/* The relationship of VersionCtx is implemented using a doubly linked list:
|
||||
* 0、data represents the root node of this data signature
|
||||
* 1、Non-nested scenes: v1<—>v2<—>v3<—>data
|
||||
* 2、Nested scenes: v1<—>v2.1<—>v2.2<—>v2<—>v3<—>data
|
||||
*/
|
||||
|
||||
struct VersionCtx : private NonCopyable {
|
||||
VersionCtx(const void* signature, VersionCtx* next, VersionCtx* last)
|
||||
: signature(signature), next(next), last(last) {};
|
||||
// Unique identifier for the data, taking the memory address of the actual data
|
||||
const void* signature;
|
||||
|
||||
// Nested scenes, is next version, in non-nested scenes, is the next sub version's parent version
|
||||
VersionCtx* next {nullptr};
|
||||
// Non-nested scenes, is last version, in nested scenes, is the parent's last sub version
|
||||
VersionCtx* last {nullptr};
|
||||
|
||||
// Current version's consumers, notify all when ready
|
||||
std::unordered_set<SCPUEUTask*> consumers;
|
||||
// Current version's producer
|
||||
SCPUEUTask* myProducer {nullptr};
|
||||
// Next version's producer, notify when consumed
|
||||
SCPUEUTask* nextProducer {nullptr};
|
||||
|
||||
DataStatus status {DataStatus::IDLE};
|
||||
std::vector<SCPUEUTask*> dataWaitTaskByThis;
|
||||
|
||||
void AddConsumer(SCPUEUTask* consumer, NestType nestType);
|
||||
void AddProducer(SCPUEUTask* producer);
|
||||
inline void AddDataWaitTaskByThis(SCPUEUTask* dataWaitTask)
|
||||
{
|
||||
if (last != nullptr && last->status == DataStatus::IDLE) {
|
||||
auto waitVersion = last;
|
||||
waitVersion->dataWaitTaskByThis.push_back(dataWaitTask);
|
||||
dataWaitTask->IncWaitDataRef();
|
||||
}
|
||||
}
|
||||
void onProduced();
|
||||
void onConsumed(SCPUEUTask* consumer);
|
||||
protected:
|
||||
void CreateChildVersion(SCPUEUTask* task, DataStatus dataStatus);
|
||||
void MergeChildVersion();
|
||||
inline void NotifyDataWaitTask()
|
||||
{
|
||||
for (auto& dataWaitTask : std::as_const(dataWaitTaskByThis)) {
|
||||
dataWaitTask->DecWaitDataRef();
|
||||
}
|
||||
dataWaitTaskByThis.clear();
|
||||
}
|
||||
|
||||
inline void NotifyConsumers()
|
||||
{
|
||||
for (auto consumer : std::as_const(consumers)) {
|
||||
consumer->DecDepRef();
|
||||
}
|
||||
}
|
||||
|
||||
inline void NotifyNextProducer()
|
||||
{
|
||||
if (nextProducer != nullptr) {
|
||||
nextProducer->DecDepRef();
|
||||
nextProducer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline void MergeConsumerInDep(VersionCtx* v)
|
||||
{
|
||||
for (const auto& consumer : std::as_const(v->consumers)) {
|
||||
consumer->ins.insert(this);
|
||||
consumer->ins.erase(consumer->ins.find(v));
|
||||
}
|
||||
}
|
||||
|
||||
inline void MergeProducerOutDep(VersionCtx* v)
|
||||
{
|
||||
v->myProducer->outs.insert(this);
|
||||
v->myProducer->outs.erase(v->myProducer->outs.find(v));
|
||||
}
|
||||
};
|
||||
} /* namespace ffrt */
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 FFRT_DFX_ASYNC_STACK_H
|
||||
#define FFRT_DFX_ASYNC_STACK_H
|
||||
#include <cinttypes>
|
||||
namespace ffrt {
|
||||
uint64_t FFRTCollectAsyncStack(void);
|
||||
void FFRTSetStackId(uint64_t stackId);
|
||||
void CloseAsyncStackLibHandle();
|
||||
}
|
||||
#endif /* FFRT_DFX_ASYNC_STACK_H */
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 __FFRT_BBOX_H__
|
||||
#define __FFRT_BBOX_H__
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
|
||||
#include <string>
|
||||
|
||||
extern void TaskWakeCounterInc(void);
|
||||
extern void TaskPendingCounterInc(void);
|
||||
extern unsigned int GetBboxEnableState(void);
|
||||
extern unsigned int GetBboxCalledTimes(void);
|
||||
|
||||
typedef void (*FuncGetKeyStatus)();
|
||||
typedef void (*FuncSaveKeyStatus)();
|
||||
typedef std::string (*FuncSaveKeyStatusInfo)();
|
||||
std::string SaveKeyInfo(void);
|
||||
void SetFuncSaveKeyStatus(FuncGetKeyStatus getFunc, FuncSaveKeyStatus saveFunc, FuncSaveKeyStatusInfo infoFunc);
|
||||
|
||||
// undefine in header for non-inline to explain why stop
|
||||
void BboxFreeze(void);
|
||||
|
||||
// define in header for inline to speedup
|
||||
static inline void BboxCheckAndFreeze(void)
|
||||
{
|
||||
if (GetBboxEnableState() != 0) {
|
||||
BboxFreeze();
|
||||
}
|
||||
}
|
||||
|
||||
bool FFRTIsWork(void);
|
||||
void RecordDebugInfo(void);
|
||||
|
||||
std::string GetDumpPreface(void);
|
||||
#ifdef FFRT_CO_BACKTRACE_OH_ENABLE
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
std::string SaveTaskCounterInfo(void);
|
||||
#endif
|
||||
std::string SaveWorkerStatusInfo(void);
|
||||
std::string SaveNormalTaskStatusInfo(void);
|
||||
std::string SaveQueueTaskStatusInfo(void);
|
||||
std::string SaveTimeoutTaskInfo(void);
|
||||
std::string SaveQueueTrafficRecordInfo(void);
|
||||
#endif
|
||||
#else
|
||||
static inline void BboxCheckAndFreeze(void)
|
||||
{}
|
||||
#endif /* FFRT_BBOX_ENABLE */
|
||||
void backtrace(int ignoreDepth);
|
||||
#endif /* __FFRT_BBOX_H__ */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 __FAULT_LOGGER_FD_MANAGER_H__
|
||||
#define __FAULT_LOGGER_FD_MANAGER_H__
|
||||
|
||||
class FaultLoggerFdManager {
|
||||
public:
|
||||
static int InitFaultLoggerFd();
|
||||
static void CloseFd();
|
||||
static int GetFaultLoggerFd();
|
||||
static void WriteFaultLogger(const char* format, ...);
|
||||
private:
|
||||
static int faultLoggerFd_;
|
||||
};
|
||||
#endif /* __FAULT_LOGGER_FD_MANAGER_H__ */
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 __FFRT_LOG_API_H__
|
||||
#define __FFRT_LOG_API_H__
|
||||
|
||||
#ifdef OHOS_STANDARD_SYSTEM
|
||||
#include <array>
|
||||
#ifdef FFRT_ENG_DEBUG
|
||||
#include <info/fatal_message.h>
|
||||
#endif
|
||||
#include <string_view>
|
||||
#include "hilog/log.h"
|
||||
#include "internal_inc/osal.h"
|
||||
#include "dfx/bbox/fault_logger_fd_manager.h"
|
||||
#else
|
||||
#include "log_base.h"
|
||||
#endif
|
||||
|
||||
#define FFRT_LOG_ERROR (0)
|
||||
#define FFRT_LOG_WARN (1)
|
||||
#define FFRT_LOG_INFO (2)
|
||||
#define FFRT_LOG_DEBUG (3)
|
||||
#define FFRT_LOG_LEVEL_MAX (FFRT_LOG_DEBUG + 1)
|
||||
|
||||
unsigned int GetLogId(void);
|
||||
bool IsInWhitelist(void);
|
||||
void InitWhiteListFlag(void);
|
||||
#ifdef FFRT_SEND_EVENT
|
||||
void ReportSysEvent(const char* format, ...);
|
||||
#endif
|
||||
|
||||
#ifdef OHOS_STANDARD_SYSTEM
|
||||
template<size_t N>
|
||||
constexpr auto convertFmtToPublic(const char(&str)[N])
|
||||
{
|
||||
constexpr std::string_view fmtpub = "{public}";
|
||||
std::array<char, (N / 2) * fmtpub.size() + N> res{};
|
||||
for (size_t i = 0, j = 0; i < N; ++i) {
|
||||
res[j++] = str[i];
|
||||
if (str[i] != '%') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str[i + 1] != '%' && str[i + 1] != '{') {
|
||||
for (size_t k = 0; k < fmtpub.size(); ++k) {
|
||||
res[j++] = fmtpub[k];
|
||||
}
|
||||
} else {
|
||||
res[j++] = str[i + 1];
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef HILOG_FMTID
|
||||
#define HILOG_IMPL_STD_ARRAY(type, level, fmt, ...) \
|
||||
do { \
|
||||
constexpr HILOG_FMT_IN_SECTION static auto hilogFmt = fmt; \
|
||||
FmtId fmtid{ HILOG_UUID, HILOG_FMT_OFFSET(hilogFmt.data()) }; \
|
||||
HiLogPrintDict(type, level, 0xD001719, "ffrt", &fmtid, hilogFmt.data(), ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HILOG_IMPL_STD_ARRAY(type, level, fmt, ...) \
|
||||
do { \
|
||||
HiLogPrint(type, level, 0xD001719, "ffrt", fmt.data(), ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if (FFRT_LOG_LEVEL >= FFRT_LOG_DEBUG)
|
||||
#define FFRT_LOGD(format, ...) \
|
||||
do { \
|
||||
if (unlikely(IsInWhitelist())) { \
|
||||
constexpr auto fmtPub = convertFmtToPublic("%u:%s:%d " format); \
|
||||
HILOG_IMPL_STD_ARRAY(LOG_CORE, LOG_DEBUG, fmtPub, GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define FFRT_LOGD(format, ...)
|
||||
#endif
|
||||
|
||||
#if (FFRT_LOG_LEVEL >= FFRT_LOG_INFO)
|
||||
#define FFRT_LOGI(format, ...) \
|
||||
do { \
|
||||
constexpr auto fmtPub = convertFmtToPublic("%u:%s:%d " format); \
|
||||
HILOG_IMPL_STD_ARRAY(LOG_CORE, LOG_INFO, fmtPub, GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FFRT_LOGI(format, ...)
|
||||
#endif
|
||||
|
||||
#if (FFRT_LOG_LEVEL >= FFRT_LOG_WARN)
|
||||
#define FFRT_LOGW(format, ...) \
|
||||
do { \
|
||||
constexpr auto fmtPub = convertFmtToPublic("%u:%s:%d " format); \
|
||||
HILOG_IMPL_STD_ARRAY(LOG_CORE, LOG_WARN, fmtPub, GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FFRT_LOGW(format, ...)
|
||||
#endif
|
||||
|
||||
#define FFRT_LOGE(format, ...) \
|
||||
do { \
|
||||
constexpr auto fmtPub = convertFmtToPublic("%u:%s:%d " format); \
|
||||
HILOG_IMPL_STD_ARRAY(LOG_CORE, LOG_ERROR, fmtPub, GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#if (FFRT_LOG_LEVEL >= FFRT_LOG_DEBUG)
|
||||
#define FFRT_LOGD(format, ...) FFRT_LOG(FFRT_LOG_DEBUG, format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define FFRT_LOGD(format, ...)
|
||||
#endif
|
||||
|
||||
#if (FFRT_LOG_LEVEL >= FFRT_LOG_INFO)
|
||||
#define FFRT_LOGI(format, ...) FFRT_LOG(FFRT_LOG_INFO, format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define FFRT_LOGI(format, ...)
|
||||
#endif
|
||||
|
||||
#if (FFRT_LOG_LEVEL >= FFRT_LOG_WARN)
|
||||
#define FFRT_LOGW(format, ...) FFRT_LOG(FFRT_LOG_WARN, format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define FFRT_LOGW(format, ...)
|
||||
#endif
|
||||
|
||||
#define FFRT_LOGE(format, ...) FFRT_LOG(FFRT_LOG_ERROR, format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OHOS_STANDARD_SYSTEM
|
||||
#define FFRT_BBOX_LOG(format, ...) \
|
||||
do { \
|
||||
FFRT_LOGE(format, ##__VA_ARGS__); \
|
||||
FaultLoggerFdManager::WriteFaultLogger(format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FFRT_BBOX_LOG(format, ...) FFRT_LOGE(format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef FFRT_SEND_EVENT
|
||||
#define FFRT_SYSEVENT_LOGE(format, ...) \
|
||||
do { \
|
||||
FFRT_LOGE(format, ##__VA_ARGS__); \
|
||||
ReportSysEvent(format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define FFRT_SYSEVENT_LOGW(format, ...) \
|
||||
do { \
|
||||
FFRT_LOGW(format, ##__VA_ARGS__); \
|
||||
ReportSysEvent(format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define FFRT_SYSEVENT_LOGI(format, ...) \
|
||||
do { \
|
||||
FFRT_LOGI(format, ##__VA_ARGS__); \
|
||||
ReportSysEvent(format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define FFRT_SYSEVENT_LOGD(format, ...) \
|
||||
do { \
|
||||
FFRT_LOGD(format, ##__VA_ARGS__); \
|
||||
ReportSysEvent(format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else // FFRT_SEND_EVENT
|
||||
#define FFRT_SYSEVENT_LOGE(format, ...) FFRT_LOGE(format, ##__VA_ARGS__)
|
||||
#define FFRT_SYSEVENT_LOGW(format, ...) FFRT_LOGW(format, ##__VA_ARGS__)
|
||||
#define FFRT_SYSEVENT_LOGI(format, ...) FFRT_LOGI(format, ##__VA_ARGS__)
|
||||
#define FFRT_SYSEVENT_LOGD(format, ...) FFRT_LOGD(format, ##__VA_ARGS__)
|
||||
#endif // FFRT_SEND_EVENT
|
||||
|
||||
#define FFRT_COND_DO_ERR(cond, expr, format, ...) \
|
||||
if (cond) { \
|
||||
FFRT_LOGE(format, ##__VA_ARGS__); \
|
||||
{ \
|
||||
expr; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Do not use this Marco directly
|
||||
#define COND_RETURN_(COND, ERRCODE, ...) \
|
||||
if ((COND)) { \
|
||||
FFRT_LOGE(__VA_ARGS__); \
|
||||
return ERRCODE; \
|
||||
}
|
||||
|
||||
#define FFRT_COND_RETURN_ERROR(COND, ERRCODE, ...) \
|
||||
COND_RETURN_((COND), ERRCODE, ##__VA_ARGS__)
|
||||
|
||||
#define FFRT_COND_RETURN_VOID(COND, ...) \
|
||||
if ((COND)) { \
|
||||
FFRT_LOGE(__VA_ARGS__); \
|
||||
return; \
|
||||
}
|
||||
|
||||
// Do not use this Marco directly
|
||||
#define COND_GOTO_WITH_ERRCODE_(COND, LABEL, ERROR, ERRCODE, ...) \
|
||||
if ((COND)) { \
|
||||
FFRT_LOGE(__VA_ARGS__); \
|
||||
ERROR = (ERRCODE); \
|
||||
goto LABEL; \
|
||||
}
|
||||
|
||||
#define FFRT_COND_GOTO_ERROR(COND, LABEL, ERROR, ERRCODE, ...) \
|
||||
COND_GOTO_WITH_ERRCODE_((COND), LABEL, ERROR, ERRCODE, ##__VA_ARGS__)
|
||||
|
||||
#define FFRT_UNUSED(expr) \
|
||||
do { \
|
||||
(void)(expr); \
|
||||
} while (0)
|
||||
|
||||
#if defined(FFRT_ENG_DEBUG) && defined(OHOS_STANDARD_SYSTEM)
|
||||
#define FFRT_UNLIKELY_COND_DO_ABORT(cond, fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(cond)) { \
|
||||
char fatal_msg[256]; \
|
||||
snprintf_s(fatal_msg, sizeof(fatal_msg), sizeof(fatal_msg) - 1, fmt, ##__VA_ARGS__); \
|
||||
FFRT_LOGE(fmt, ##__VA_ARGS__); \
|
||||
set_fatal_message(fatal_msg); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define FFRT_UNLIKELY_COND_DO_ABORT(cond, fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(cond)) { \
|
||||
FFRT_LOGE(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif // FFRT_ENG_DEBUG
|
||||
|
||||
#if defined(FFRT_ENG_DEBUG) && defined(OHOS_STANDARD_SYSTEM)
|
||||
#define FFRT_COND_TERMINATE(cond, fmt, ...) \
|
||||
do { \
|
||||
if (cond) { \
|
||||
char fatal_msg[256]; \
|
||||
snprintf_s(fatal_msg, sizeof(fatal_msg), sizeof(fatal_msg) - 1, fmt, ##__VA_ARGS__); \
|
||||
FFRT_SYSEVENT_LOGE(fmt, ##__VA_ARGS__); \
|
||||
set_fatal_message(fatal_msg); \
|
||||
std::terminate(); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define FFRT_COND_TERMINATE(cond, fmt, ...) \
|
||||
do { \
|
||||
if (cond) { \
|
||||
FFRT_SYSEVENT_LOGE(fmt, ##__VA_ARGS__); \
|
||||
std::terminate(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif // FFRT_ENG_DEBUG
|
||||
#endif // __FFRT_LOG_API_H__
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 __LOG_BASE_H__
|
||||
#define __LOG_BASE_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void LogErr(const char* format, ...);
|
||||
void LogWarn(const char* format, ...);
|
||||
void LogInfo(const char* format, ...);
|
||||
void LogDebug(const char* format, ...);
|
||||
|
||||
int GetFFRTLogLevel(void);
|
||||
|
||||
#define FFRT_LOG(level, format, ...) \
|
||||
do { \
|
||||
if ((level) > GetFFRTLogLevel()) \
|
||||
break; \
|
||||
if (level == FFRT_LOG_ERROR) { \
|
||||
LogErr("%u:%s:%d " format "\n", GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} else if (level == FFRT_LOG_WARN) { \
|
||||
LogWarn("%u:%s:%d " format "\n", GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} else if (level == FFRT_LOG_INFO) { \
|
||||
LogInfo("%u:%s:%d " format "\n", GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} else if (level == FFRT_LOG_DEBUG) { \
|
||||
LogDebug("%u:%s:%d " format "\n", GetLogId(), __func__, __LINE__, ##__VA_ARGS__); \
|
||||
} else { \
|
||||
printf("Log Level is Invalid!"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // __LOG_BASE_H__
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 __FFRT_TRACE_H__
|
||||
#define __FFRT_TRACE_H__
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include "internal_inc/osal.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
|
||||
#ifdef FFRT_OH_TRACE_ENABLE
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
enum TraceLevel {
|
||||
TRACE_LEVEL0 = 0,
|
||||
TRACE_LEVEL1,
|
||||
TRACE_LEVEL2,
|
||||
TRACE_LEVEL3, // lowest level, trace all
|
||||
TRACE_LEVEL_MAX,
|
||||
};
|
||||
|
||||
class TraceLevelManager {
|
||||
public:
|
||||
TraceLevelManager();
|
||||
~TraceLevelManager() = default;
|
||||
|
||||
uint64_t GetTraceLevel() const
|
||||
{
|
||||
return traceLevel_;
|
||||
}
|
||||
|
||||
static inline TraceLevelManager* Instance()
|
||||
{
|
||||
static TraceLevelManager ins;
|
||||
return &ins;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t traceLevel_;
|
||||
};
|
||||
|
||||
class ScopedTrace {
|
||||
public:
|
||||
ScopedTrace(uint64_t level, const char* name);
|
||||
~ScopedTrace();
|
||||
|
||||
private:
|
||||
std::atomic<bool> isTraceEnable_;
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#ifdef FFRT_OH_TRACE_ENABLE
|
||||
constexpr uint64_t HITRACE_TAG_FFRT = (1ULL << 13); // ffrt tasks.
|
||||
bool IsTagEnabled(uint64_t tag);
|
||||
void StartTrace(uint64_t label, const std::string& value, float limit = -1);
|
||||
void FinishTrace(uint64_t label);
|
||||
void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit = -1);
|
||||
void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId);
|
||||
void CountTrace(uint64_t label, const std::string& name, int64_t count);
|
||||
#ifdef APP_USE_ARM
|
||||
constexpr const char* TRACE_LIB_PATH = "libhitrace_meter.so";
|
||||
#else
|
||||
constexpr const char* TRACE_LIB_PATH = "libhitrace_meter.so";
|
||||
#endif
|
||||
class TraceAdapter {
|
||||
public:
|
||||
TraceAdapter()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
~TraceAdapter()
|
||||
{
|
||||
UnLoad();
|
||||
}
|
||||
|
||||
static TraceAdapter* Instance()
|
||||
{
|
||||
static TraceAdapter instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
#define REG_FUNC(func) using func##Type = decltype(func)*; func##Type func = nullptr
|
||||
REG_FUNC(IsTagEnabled);
|
||||
REG_FUNC(StartTrace);
|
||||
REG_FUNC(FinishTrace);
|
||||
REG_FUNC(StartAsyncTrace);
|
||||
REG_FUNC(FinishAsyncTrace);
|
||||
REG_FUNC(CountTrace);
|
||||
#undef REG_FUNC
|
||||
|
||||
private:
|
||||
bool Load()
|
||||
{
|
||||
if (handle != nullptr) {
|
||||
FFRT_LOGD("handle exits");
|
||||
return true;
|
||||
}
|
||||
|
||||
handle = dlopen(TRACE_LIB_PATH, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
|
||||
if (handle == nullptr) {
|
||||
FFRT_LOGE("load so[%s] fail", TRACE_LIB_PATH);
|
||||
return false;
|
||||
}
|
||||
|
||||
#define LOAD_FUNC(x) x = reinterpret_cast<x##Type>(dlsym(handle, #x)); \
|
||||
if (x == nullptr) \
|
||||
{ \
|
||||
FFRT_LOGE("load func %s from %s failed", #x, TRACE_LIB_PATH); \
|
||||
return false; \
|
||||
}
|
||||
LOAD_FUNC(IsTagEnabled);
|
||||
LOAD_FUNC(StartTrace);
|
||||
LOAD_FUNC(FinishTrace);
|
||||
LOAD_FUNC(StartAsyncTrace);
|
||||
LOAD_FUNC(FinishAsyncTrace);
|
||||
LOAD_FUNC(CountTrace);
|
||||
#undef LOAD_FUNC
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnLoad()
|
||||
{
|
||||
if (handle != nullptr) {
|
||||
if (dlclose(handle) != 0) {
|
||||
return false;
|
||||
}
|
||||
handle = nullptr;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void* handle = nullptr;
|
||||
};
|
||||
|
||||
#define GET_TRACE_FUNC(x) (TraceAdapter::Instance()->x)
|
||||
|
||||
static bool _IsTagEnabled(uint64_t label)
|
||||
{
|
||||
auto func = GET_TRACE_FUNC(IsTagEnabled);
|
||||
if (func != nullptr) {
|
||||
return func(label);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#define _StartTrace(label, tag, limit) \
|
||||
do { \
|
||||
auto func = GET_TRACE_FUNC(StartTrace); \
|
||||
if (func != nullptr) { \
|
||||
func(label, tag, limit); \
|
||||
} \
|
||||
} while (0)
|
||||
#define _FinishTrace(label) \
|
||||
do { \
|
||||
auto func = GET_TRACE_FUNC(FinishTrace); \
|
||||
if (func != nullptr) { \
|
||||
func(label); \
|
||||
} \
|
||||
} while (0)
|
||||
#define _StartAsyncTrace(label, tag, tid, limit) \
|
||||
do { \
|
||||
auto func = GET_TRACE_FUNC(StartAsyncTrace); \
|
||||
if (func != nullptr) { \
|
||||
func(label, tag, tid, limit); \
|
||||
} \
|
||||
} while (0)
|
||||
#define _FinishAsyncTrace(label, tag, tid) \
|
||||
do { \
|
||||
auto func = GET_TRACE_FUNC(FinishAsyncTrace); \
|
||||
if (func != nullptr) { \
|
||||
func(label, tag, tid); \
|
||||
} \
|
||||
} while (0)
|
||||
#define _TraceCount(label, tag, value) \
|
||||
do { \
|
||||
auto func = GET_TRACE_FUNC(CountTrace); \
|
||||
if (func != nullptr) { \
|
||||
func(label, tag, value); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FFRT_TRACE_BEGIN(tag) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_StartTrace(HITRACE_TAG_FFRT, tag, -1); \
|
||||
} while (false)
|
||||
#define FFRT_TRACE_END() \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_FinishTrace(HITRACE_TAG_FFRT); \
|
||||
} while (false)
|
||||
#define FFRT_TRACE_ASYNC_BEGIN(tag, tid) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_StartAsyncTrace(HITRACE_TAG_FFRT, tag, tid, -1); \
|
||||
} while (false)
|
||||
#define FFRT_TRACE_ASYNC_END(tag, tid) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_FinishAsyncTrace(HITRACE_TAG_FFRT, tag, tid); \
|
||||
} while (false)
|
||||
#define FFRT_TRACE_COUNT(tag, value) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_TraceCount(HITRACE_TAG_FFRT, tag, value); \
|
||||
} while (false)
|
||||
#define FFRT_SUBMIT_MARKER(gid) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) { \
|
||||
_StartTrace(HITRACE_TAG_FFRT, ("P " + std::to_string(gid)).c_str(), -1); \
|
||||
} \
|
||||
} while (false)
|
||||
#define FFRT_TASK_BEGIN(tag, gid) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) { \
|
||||
_StartTrace(HITRACE_TAG_FFRT, ("FFRT" + (tag) + "|" + std::to_string(gid)).c_str(), -1); \
|
||||
} \
|
||||
} while (false)
|
||||
#define FFRT_BLOCK_TRACER(gid, tag) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_StartTrace(HITRACE_TAG_FFRT, ("FFBK" #tag "|" + std::to_string(gid)).c_str(), -1); \
|
||||
FFRT_TRACE_END(); \
|
||||
} while (false)
|
||||
#define FFRT_WAKE_TRACER(gid) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_StartTrace(HITRACE_TAG_FFRT, ("FFWK|" + std::to_string(gid)).c_str(), -1); \
|
||||
FFRT_TRACE_END(); \
|
||||
} while (false)
|
||||
#define FFRT_EXECUTOR_TASK_BEGIN(gid) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_StartTrace(HITRACE_TAG_FFRT, ("FFRTex_task|" + std::to_string(gid)).c_str(), -1); \
|
||||
} while (false)
|
||||
#define FFRT_SERIAL_QUEUE_TASK_SUBMIT_MARKER(qid, gid) \
|
||||
do { \
|
||||
if (__builtin_expect(!!(_IsTagEnabled(HITRACE_TAG_FFRT)), 0)) \
|
||||
_StartTrace(HITRACE_TAG_FFRT, ("P[sq_" + \
|
||||
std::to_string(qid) + "]|" + std::to_string(gid)).c_str(), -1); \
|
||||
FFRT_TRACE_END(); \
|
||||
} while (false)
|
||||
#define FFRT_TRACE_SCOPE(level, tag) ffrt::ScopedTrace ___tracer##tag(level, #tag)
|
||||
#else
|
||||
#define FFRT_TRACE_BEGIN(tag)
|
||||
#define FFRT_TRACE_END()
|
||||
#define FFRT_TRACE_ASYNC_BEGIN(tag, tid)
|
||||
#define FFRT_TRACE_ASYNC_END(tag, tid)
|
||||
#define FFRT_TRACE_COUNT(tag, value)
|
||||
#define FFRT_TRACE_SCOPE(level, tag)
|
||||
#define FFRT_SUBMIT_MARKER(gid)
|
||||
#define FFRT_TASK_BEGIN(tag, gid)
|
||||
#define FFRT_BLOCK_TRACER(gid, tag)
|
||||
#define FFRT_WAKE_TRACER(gid)
|
||||
#define FFRT_EXECUTOR_TASK_BEGIN(gid)
|
||||
#define FFRT_SERIAL_QUEUE_TASK_SUBMIT_MARKER(qid, gid)
|
||||
#endif
|
||||
|
||||
// DFX Trace for FFRT Normal Task
|
||||
#define FFRT_WORKER_IDLE_BEGIN_MARKER()
|
||||
#define FFRT_WORKER_IDLE_END_MARKER()
|
||||
#define FFRT_READY_MARKER(gid) \
|
||||
{ \
|
||||
FFRT_TRACE_ASYNC_END("R", gid); \
|
||||
}
|
||||
#define FFRT_BLOCK_MARKER(gid) \
|
||||
{ \
|
||||
FFRT_TRACE_ASYNC_END("B", gid); \
|
||||
}
|
||||
#define FFRT_TASKDONE_MARKER(gid) \
|
||||
{ \
|
||||
FFRT_TRACE_ASYNC_END("F", gid); \
|
||||
}
|
||||
#define FFRT_TASK_END() \
|
||||
{ \
|
||||
FFRT_TRACE_END(); \
|
||||
}
|
||||
// DFX Trace for FFRT Executor Task
|
||||
#define FFRT_EXECUTOR_TASK_SUBMIT_MARKER(gid) \
|
||||
{ \
|
||||
FFRT_TRACE_ASYNC_END("P", gid); \
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 __FFRT_TRACE_CHAIN_H__
|
||||
#define __FFRT_TRACE_CHAIN_H__
|
||||
|
||||
#include "tm/task_base.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
|
||||
namespace ffrt {
|
||||
|
||||
class TraceChainAdapter {
|
||||
public:
|
||||
TraceChainAdapter();
|
||||
~TraceChainAdapter();
|
||||
|
||||
static TraceChainAdapter& Instance();
|
||||
|
||||
HiTraceIdStruct HiTraceChainGetId();
|
||||
void HiTraceChainClearId();
|
||||
void HiTraceChainRestoreId(const HiTraceIdStruct* pId);
|
||||
HiTraceIdStruct HiTraceChainCreateSpan();
|
||||
HiTraceIdStruct HiTraceChainBegin(const char* name, int flags);
|
||||
void HiTraceChainEnd(const HiTraceIdStruct* pId);
|
||||
|
||||
private:
|
||||
void Load();
|
||||
void UnLoad();
|
||||
|
||||
void* handle_ = nullptr;
|
||||
|
||||
using HiTraceChainGetIdFunc = HiTraceIdStruct (*)();
|
||||
using HiTraceChainClearIdFunc = void (*)();
|
||||
using HiTraceChainRestoreIdFunc = void (*)(const HiTraceIdStruct*);
|
||||
using HiTraceChainCreateSpanFunc = HiTraceIdStruct (*)();
|
||||
using HiTraceChainBeginFunc = HiTraceIdStruct (*)(const char*, int);
|
||||
using HiTraceChainEndFunc = void (*)(const HiTraceIdStruct*);
|
||||
|
||||
HiTraceChainGetIdFunc getIdFunc_ = nullptr;
|
||||
HiTraceChainClearIdFunc clearIdFunc_ = nullptr;
|
||||
HiTraceChainRestoreIdFunc restoreIdFunc_ = nullptr;
|
||||
HiTraceChainCreateSpanFunc createSpanFunc_ = nullptr;
|
||||
HiTraceChainBeginFunc beginChainFunc_ = nullptr;
|
||||
HiTraceChainEndFunc endChainFunc_ = nullptr;
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // __FFRT_TRACE_CHAIN_H__
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_TRACE_RECORD_H
|
||||
#define FFRT_TRACE_RECORD_H
|
||||
|
||||
#include "util/ffrt_ring_buffer.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
#include "internal_inc/osal.h"
|
||||
#include "tm/task_base.h"
|
||||
#include "tm/cpu_task.h"
|
||||
#include "tm/queue_task.h"
|
||||
|
||||
#define FFRT_TRACE_RECORD_LEVEL_1 (1)
|
||||
#define FFRT_TRACE_RECORD_LEVEL_2 (2)
|
||||
#define FFRT_TRACE_RECORD_LEVEL_3 (3)
|
||||
|
||||
namespace ffrt {
|
||||
typedef struct ffrt_record_task_counter {
|
||||
alignas(cacheline_size) std::atomic<unsigned int> submitCounter{0};
|
||||
alignas(cacheline_size) std::atomic<unsigned int> enqueueCounter{0};
|
||||
alignas(cacheline_size) std::atomic<unsigned int> coSwitchCounter{0};
|
||||
alignas(cacheline_size) std::atomic<unsigned int> runCounter{0};
|
||||
alignas(cacheline_size) std::atomic<unsigned int> doneCounter{0};
|
||||
alignas(cacheline_size) std::atomic<unsigned int> cancelCounter{0};
|
||||
} ffrt_record_task_counter_t;
|
||||
|
||||
typedef struct ffrt_record_task_time {
|
||||
std::atomic<uint64_t> waitTime{0};
|
||||
std::atomic<uint64_t> runDuration{0};
|
||||
std::atomic<uint64_t> executeTime{0};
|
||||
uint64_t maxWaitTime{0};
|
||||
uint64_t maxRunDuration{0};
|
||||
} ffrt_record_task_time_t;
|
||||
|
||||
class FFRTTraceRecord {
|
||||
public:
|
||||
static const int TASK_TYPE_NUM = ffrt_queue_task + 1;
|
||||
static std::atomic<bool> ffrt_be_used_;
|
||||
static bool stat_enable_;
|
||||
static int g_recordMaxWorkerNumber_[QoS::MaxNum()];
|
||||
static ffrt_record_task_counter_t g_recordTaskCounter_[TASK_TYPE_NUM][QoS::MaxNum()];
|
||||
static ffrt_record_task_time_t g_recordTaskTime_[TASK_TYPE_NUM][QoS::MaxNum()];
|
||||
|
||||
public:
|
||||
FFRTTraceRecord() = default;
|
||||
~FFRTTraceRecord() = default;
|
||||
|
||||
static inline bool FfrtBeUsed()
|
||||
{
|
||||
return ffrt_be_used_;
|
||||
}
|
||||
|
||||
static int StatEnable(char *buf, uint32_t len)
|
||||
{
|
||||
if (len < TASK_STAT_LENGTH) {
|
||||
FFRT_LOGE("Buffer size is not enough, len = %u", len);
|
||||
return -1;
|
||||
}
|
||||
if (stat_enable_) {
|
||||
FFRT_LOGW("Statistics are already enabled.");
|
||||
return -1;
|
||||
}
|
||||
if (ringBuffer_ != nullptr) {
|
||||
FFRT_LOGW(
|
||||
"Buffer has been set, do not set again. "
|
||||
"Previous buffer start addr = %p, size = %u",
|
||||
ringBuffer_->GetBuffer(), ringBuffer_->GetBufferSize());
|
||||
return -1;
|
||||
}
|
||||
ringBuffer_ = std::make_unique<FFRTRingBuffer>(buf, len);
|
||||
stat_enable_ = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int StatsDisable(char *buf)
|
||||
{
|
||||
FFRT_LOGW("StatsDisable");
|
||||
if (ringBuffer_ == nullptr) {
|
||||
FFRT_LOGW("StatsDisable: ringBuffer_ is already nullptr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf != ringBuffer_->GetBuffer()) {
|
||||
FFRT_LOGW(
|
||||
"Buffer addr invalid "
|
||||
"Previous buffer addr = %p, now is = %p",
|
||||
ringBuffer_->GetBuffer(), buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
stat_enable_ = false;
|
||||
ringBuffer_.reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void UseFfrt()
|
||||
{
|
||||
if (unlikely(!ffrt_be_used_)) {
|
||||
ffrt_be_used_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
template<ffrt_executor_task_type_t taskType>
|
||||
static inline void TaskSubmit(int qos)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[taskType][qos].submitCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void TaskSubmit(uint64_t* createTime, int32_t* fromTid)
|
||||
{
|
||||
*createTime = TimeStamp();
|
||||
*fromTid = ExecuteCtx::Cur()->tid;
|
||||
}
|
||||
|
||||
template<ffrt_executor_task_type_t taskType>
|
||||
static inline void TaskSubmit(int qos, uint64_t* createTime, int32_t* fromTid)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[taskType][qos].submitCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
*createTime = TimeStamp();
|
||||
*fromTid = ExecuteCtx::Cur()->tid;
|
||||
}
|
||||
|
||||
static inline void TaskExecute(uint64_t* executeTime)
|
||||
{
|
||||
*executeTime = TimeStamp();
|
||||
}
|
||||
|
||||
template<ffrt_executor_task_type_t taskType>
|
||||
static inline void TaskExecute(int qos)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[taskType][qos].runCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<ffrt_executor_task_type_t taskType>
|
||||
static inline void TaskDone(int qos)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[taskType][qos].doneCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<ffrt_executor_task_type_t taskType>
|
||||
static void TaskDone(int qos, TaskBase* task)
|
||||
{
|
||||
if (stat_enable_) {
|
||||
uint64_t endTime = TimeStamp();
|
||||
ffrt_stat stat;
|
||||
errno_t ret;
|
||||
if (taskType == ffrt_normal_task) {
|
||||
auto baseTask = reinterpret_cast<CPUEUTask*>(task);
|
||||
auto f = reinterpret_cast<ffrt_function_header_t*>(baseTask->func_storage);
|
||||
baseTask->label.resize(MAX_TASK_NAME_LENGTH - 1, ' ');
|
||||
ret = strcpy_s(stat.taskName, MAX_TASK_NAME_LENGTH, baseTask->GetLabel().c_str());
|
||||
stat.funcPtr = reinterpret_cast<uint64_t>(f->exec);
|
||||
}
|
||||
if (taskType == ffrt_queue_task) {
|
||||
auto baseTask = reinterpret_cast<QueueTask*>(task);
|
||||
auto f = reinterpret_cast<ffrt_function_header_t*>(baseTask->func_storage);
|
||||
baseTask->label.resize(MAX_TASK_NAME_LENGTH - 1, ' ');
|
||||
ret = strcpy_s(stat.taskName, MAX_TASK_NAME_LENGTH, baseTask->GetLabel().c_str());
|
||||
stat.funcPtr = reinterpret_cast<uint64_t>(f->exec);
|
||||
}
|
||||
if (ret != EOK) {
|
||||
FFRT_LOGE("strcpy_s failed");
|
||||
return;
|
||||
}
|
||||
stat.startTime = task->createTime;
|
||||
stat.endTime = endTime;
|
||||
ringBuffer_->Write(stat);
|
||||
}
|
||||
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
|
||||
auto runDuration = TimeStamp() - task->executeTime;
|
||||
g_recordTaskTime_[taskType][qos].runDuration += runDuration;
|
||||
|
||||
if (g_recordTaskTime_[taskType][qos].maxRunDuration < runDuration) {
|
||||
g_recordTaskTime_[taskType][qos].maxRunDuration = runDuration;
|
||||
}
|
||||
|
||||
auto waitTime = task->executeTime - task->createTime;
|
||||
g_recordTaskTime_[taskType][qos].waitTime += waitTime;
|
||||
if (g_recordTaskTime_[taskType][qos].maxWaitTime < waitTime) {
|
||||
g_recordTaskTime_[taskType][qos].maxWaitTime = waitTime;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<ffrt_executor_task_type_t taskType>
|
||||
static inline void TaskEnqueue(int qos)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[taskType][qos].enqueueCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<ffrt_executor_task_type_t taskType>
|
||||
static inline void TaskCancel(int qos)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[taskType][qos].cancelCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void TaskRun(int qos, TaskBase* task)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[task->type][qos].runCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void TaskCoSwitchOut(TaskBase* task)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
g_recordTaskCounter_[task->type][task->GetQos()].coSwitchCounter.fetch_add(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void WorkRecord(int qos, int workerNum)
|
||||
{
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_3)
|
||||
if (g_recordMaxWorkerNumber_[qos] < workerNum) {
|
||||
g_recordMaxWorkerNumber_[qos] = workerNum;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (FFRT_TRACE_RECORD_LEVEL >= FFRT_TRACE_RECORD_LEVEL_2)
|
||||
static int StatisticInfoDump(char* buf, uint32_t len);
|
||||
static void DumpNormalTaskStatisticInfo(std::ostringstream& oss);
|
||||
static void DumpQueueTaskStatisticInfo(std::ostringstream& oss);
|
||||
static void DumpUVTaskStatisticInfo(std::ostringstream& oss);
|
||||
|
||||
static unsigned int GetSubmitCount();
|
||||
static unsigned int GetEnqueueCount();
|
||||
static unsigned int GetRunCount();
|
||||
static unsigned int GetDoneCount();
|
||||
static unsigned int GetCoSwitchCount();
|
||||
static unsigned int GetFinishCount();
|
||||
#endif
|
||||
|
||||
private:
|
||||
static std::unique_ptr<FFRTRingBuffer> ringBuffer_;
|
||||
};
|
||||
}
|
||||
#endif // FFRT_TRACE_RECORD_H
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 WATCHDOG_UTIL_H
|
||||
#define WATCHDOG_UTIL_H
|
||||
#include "tm/cpu_task.h"
|
||||
|
||||
namespace ffrt {
|
||||
bool IsValidTimeout(uint64_t gid, uint64_t timeout_us);
|
||||
void AddTaskToWatchdog(uint64_t gid);
|
||||
void RemoveTaskFromWatchdog(uint64_t gid);
|
||||
bool SendTimeoutWatchdog(uint64_t gid, uint64_t timeout, uint64_t delay);
|
||||
void RunTimeOutCallback(uint64_t gid, uint64_t timeout);
|
||||
}
|
||||
#endif /* WATCHDOG_UTIL_H */
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_DEPENDENCE_MANAGER_H
|
||||
#define FFRT_DEPENDENCE_MANAGER_H
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include "internal_inc/types.h"
|
||||
#include "internal_inc/osal.h"
|
||||
#include "core/version_ctx.h"
|
||||
#include "sched/execute_ctx.h"
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
#include "dfx/trace/ffrt_trace.h"
|
||||
#include "sched/scheduler.h"
|
||||
#include "eu/execute_unit.h"
|
||||
#include "core/entity.h"
|
||||
#include "dfx/watchdog/watchdog_util.h"
|
||||
#include "dfx/trace_record/ffrt_trace_record.h"
|
||||
#include "tm/cpu_task.h"
|
||||
|
||||
namespace ffrt {
|
||||
#define OFFSETOF(TYPE, MEMBER) (reinterpret_cast<size_t>(&((reinterpret_cast<TYPE *>(0))->MEMBER)))
|
||||
|
||||
inline bool CheckOutsHandle(const ffrt_deps_t* outs)
|
||||
{
|
||||
if (outs == nullptr) {
|
||||
return true;
|
||||
}
|
||||
for (uint32_t i = 0; i < outs->len; i++) {
|
||||
if ((outs->items[i].type) == ffrt_dependence_task) {
|
||||
FFRT_LOGE("handle can't be used as out dependence");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline void OutsDedup(std::vector<const void *>& outsNoDup, const ffrt_deps_t* outs)
|
||||
{
|
||||
for (uint32_t i = 0; i < outs->len; i++) {
|
||||
if (std::find(outsNoDup.begin(), outsNoDup.end(), outs->items[i].ptr) == outsNoDup.end()) {
|
||||
outsNoDup.push_back(outs->items[i].ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void InsDedup(std::vector<CPUEUTask*> &in_handles, std::vector<const void *> &insNoDup,
|
||||
std::vector<const void *> &outsNoDup, const ffrt_deps_t *ins)
|
||||
{
|
||||
for (uint32_t i = 0; i < ins->len; i++) {
|
||||
if (std::find(outsNoDup.begin(), outsNoDup.end(), ins->items[i].ptr) == outsNoDup.end()) {
|
||||
if ((ins->items[i].type == ffrt_dependence_task) && (ins->items[i].ptr != nullptr)) {
|
||||
static_cast<ffrt::CPUEUTask*>(const_cast<void*>(ins->items[i].ptr))->IncDeleteRef();
|
||||
in_handles.emplace_back(static_cast<ffrt::CPUEUTask*>(const_cast<void*>(ins->items[i].ptr)));
|
||||
}
|
||||
insNoDup.push_back(ins->items[i].ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DependenceManager : public NonCopyable {
|
||||
public:
|
||||
static DependenceManager& Instance();
|
||||
|
||||
static void RegistInsCb(SingleInsCB<DependenceManager>::Instance &&cb);
|
||||
|
||||
virtual void onSubmit(bool has_handle, ffrt_task_handle_t &handle, ffrt_function_header_t *f,
|
||||
const ffrt_deps_t *ins, const ffrt_deps_t *outs, const task_attr_private *attr) = 0;
|
||||
|
||||
void onSubmitUV(ffrt_executor_task_t *task, const task_attr_private *attr);
|
||||
|
||||
void onSubmitIO(const ffrt_io_callable_t &work, const task_attr_private *attr);
|
||||
|
||||
virtual void onWait() = 0;
|
||||
|
||||
virtual void onWait(const ffrt_deps_t* deps) = 0;
|
||||
|
||||
virtual int onExecResults(ffrt_task_handle_t handle) = 0;
|
||||
|
||||
virtual void onTaskDone(CPUEUTask* task) = 0;
|
||||
|
||||
virtual int onSkip(ffrt_task_handle_t handle);
|
||||
|
||||
static inline CPUEUTask* Root()
|
||||
{
|
||||
// Within an ffrt process, different threads may have different QoS interval
|
||||
thread_local static RootTaskCtxWrapper root_wraper;
|
||||
return root_wraper.Root();
|
||||
}
|
||||
|
||||
protected:
|
||||
DependenceManager() {}
|
||||
virtual ~DependenceManager() {}
|
||||
};
|
||||
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 BLOCKAWARE_H
|
||||
#define BLOCKAWARE_H
|
||||
|
||||
#include <securec.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sys/prctl.h>
|
||||
#include <cerrno>
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLOCKAWARE_DOMAIN_ID_MAX 15
|
||||
#define HM_PR_SILK_BLOCKAWARE_OPS 0x534b4241
|
||||
#define BLOCKAWARE_SUBOPS_INIT 0x1
|
||||
#define BLOCKAWARE_SUBOPS_REG 0x2
|
||||
#define BLOCKAWARE_SUBOPS_UNREG 0x3
|
||||
#define BLOCKAWARE_SUBOPS_WAIT 0x4
|
||||
#define BLOCKAWARE_SUBOPS_WAKE 0x5
|
||||
#define BLOCKAWARE_SUBOPS_MONITORFD 0X6
|
||||
|
||||
struct BlockawareDomainInfo {
|
||||
unsigned int nrRunning;
|
||||
unsigned int nrSleeping;
|
||||
unsigned int nrBlocked;
|
||||
};
|
||||
struct BlockawareDomainInfoArea {
|
||||
struct BlockawareDomainInfo localinfo[BLOCKAWARE_DOMAIN_ID_MAX + 1];
|
||||
struct BlockawareDomainInfo globalinfo;
|
||||
};
|
||||
struct BlockawareWatermark {
|
||||
unsigned int low;
|
||||
unsigned int high;
|
||||
};
|
||||
struct BlockawareWakeupCond {
|
||||
struct BlockawareWatermark local[BLOCKAWARE_DOMAIN_ID_MAX + 1];
|
||||
struct BlockawareWatermark global;
|
||||
bool check_ahead;
|
||||
};
|
||||
struct BlockawareKinfoPageS {
|
||||
uint32_t seq;
|
||||
struct BlockawareDomainInfoArea infoArea;
|
||||
};
|
||||
|
||||
static inline int BlockawareInit(unsigned long *keyPtr);
|
||||
static inline int BlockawareRegister(unsigned int domain);
|
||||
static inline int BlockawareUnregister(void);
|
||||
static int BlockawareLoadSnapshot(unsigned long key, struct BlockawareDomainInfoArea *infoArea);
|
||||
static inline int BlockawareEnterSleeping(void);
|
||||
static inline int BlockawareLeaveSleeping(void);
|
||||
static inline int BlockawareWaitCond(struct BlockawareWakeupCond *cond);
|
||||
static inline int BlockawareWake(void);
|
||||
static inline int BlockawareMonitorfd(int fd, struct BlockawareWakeupCond *cond);
|
||||
|
||||
#ifdef __aarch64__
|
||||
static inline void CpuRelax(void)
|
||||
{
|
||||
asm volatile("yield" ::: "memory");
|
||||
}
|
||||
|
||||
static inline void SmpRmb(void)
|
||||
{
|
||||
asm volatile("dmb ishld" ::: "memory");
|
||||
}
|
||||
|
||||
static inline unsigned long GetTlsPtr(void)
|
||||
{
|
||||
unsigned long tls = 0;
|
||||
asm volatile ("mrs %0, tpidr_el0\n" : "=r" (tls));
|
||||
return tls;
|
||||
}
|
||||
|
||||
static inline unsigned long *curr_thread_tls_blockaware_slot_of(void)
|
||||
{
|
||||
unsigned long tls = GetTlsPtr();
|
||||
unsigned long slot_addr = tls - sizeof (unsigned long) * (2UL + 5UL);
|
||||
return reinterpret_cast<unsigned long *>(slot_addr);
|
||||
}
|
||||
|
||||
static inline int BlockawareEnterSleeping(void)
|
||||
{
|
||||
unsigned long *slot_ptr = curr_thread_tls_blockaware_slot_of();
|
||||
*slot_ptr += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int BlockawareLeaveSleeping(void)
|
||||
{
|
||||
unsigned long *slot_ptr = curr_thread_tls_blockaware_slot_of();
|
||||
int err = 0;
|
||||
|
||||
if (*slot_ptr == 0) {
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
*slot_ptr -= 1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#elif defined(__arm__)
|
||||
|
||||
static inline void CpuRelax(void)
|
||||
{
|
||||
asm volatile("yield" ::: "memory");
|
||||
}
|
||||
|
||||
static inline void SmpRmb(void)
|
||||
{
|
||||
asm volatile("dmb ish" ::: "memory");
|
||||
}
|
||||
|
||||
static inline unsigned long GetTlsPtr(void)
|
||||
{
|
||||
unsigned long tpid = 0;
|
||||
asm volatile("mrc p15, 0, %0, c13, c0, 3" : "=r"(tpid));
|
||||
return tpid;
|
||||
}
|
||||
|
||||
static inline unsigned long *curr_thread_tls_blockaware_slot_of(void)
|
||||
{
|
||||
unsigned long tls = GetTlsPtr();
|
||||
unsigned long slot_addr = tls - sizeof (unsigned long) * (2UL + 5UL);
|
||||
return (unsigned long *)slot_addr;
|
||||
}
|
||||
|
||||
static inline int BlockawareEnterSleeping(void)
|
||||
{
|
||||
unsigned long *slot_ptr = curr_thread_tls_blockaware_slot_of();
|
||||
*slot_ptr += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int BlockawareLeaveSleeping(void)
|
||||
{
|
||||
unsigned long *slot_ptr = curr_thread_tls_blockaware_slot_of();
|
||||
int err = 0;
|
||||
|
||||
if (*slot_ptr == 0) {
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
*slot_ptr -= 1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
static inline void CpuRelax(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void SmpRmb(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline unsigned long GetTlsPtr(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int BlockawareEnterSleeping(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int BlockawareLeaveSleeping(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int BlockawareInit(unsigned long *keyPtr)
|
||||
{
|
||||
int rc = prctl(HM_PR_SILK_BLOCKAWARE_OPS, BLOCKAWARE_SUBOPS_INIT, reinterpret_cast<unsigned long>(keyPtr));
|
||||
return (rc == 0) ? 0 : errno;
|
||||
}
|
||||
|
||||
static inline int BlockawareRegister(unsigned int domain)
|
||||
{
|
||||
/* Mention that it is kernel's responsibility to init tls slot to 0 */
|
||||
int rc = prctl(HM_PR_SILK_BLOCKAWARE_OPS, BLOCKAWARE_SUBOPS_REG, static_cast<unsigned long>(domain));
|
||||
return (rc == 0) ? 0 : errno;
|
||||
}
|
||||
|
||||
static inline int BlockawareUnregister(void)
|
||||
{
|
||||
/* Mention that it is kernel's responsibility to reset tls slot to 0 */
|
||||
int rc = prctl(HM_PR_SILK_BLOCKAWARE_OPS, BLOCKAWARE_SUBOPS_UNREG);
|
||||
return (rc == 0) ? 0 : errno;
|
||||
}
|
||||
|
||||
static inline uint32_t seqlock_start_read(const uint32_t *seq_ptr)
|
||||
{
|
||||
uint32_t seq;
|
||||
do {
|
||||
seq = *reinterpret_cast<const volatile uint32_t *>(seq_ptr);
|
||||
if ((seq & 1U) == 0U) {
|
||||
break;
|
||||
}
|
||||
CpuRelax();
|
||||
} while (true);
|
||||
SmpRmb();
|
||||
return seq;
|
||||
}
|
||||
|
||||
static inline bool seqlock_check(const uint32_t *seq_ptr, uint32_t seq_prev)
|
||||
{
|
||||
SmpRmb();
|
||||
return (*seq_ptr == seq_prev);
|
||||
}
|
||||
|
||||
static int BlockawareLoadSnapshot(unsigned long key, struct BlockawareDomainInfoArea *infoArea)
|
||||
{
|
||||
struct BlockawareKinfoPageS *kinfoPage = reinterpret_cast<struct BlockawareKinfoPageS *>(key);
|
||||
uint32_t seq;
|
||||
int ret = 0;
|
||||
do {
|
||||
seq = seqlock_start_read(&kinfoPage->seq);
|
||||
ret = memcpy_s(infoArea, sizeof(BlockawareDomainInfoArea),
|
||||
&kinfoPage->infoArea, sizeof(BlockawareDomainInfoArea));
|
||||
} while (!seqlock_check(&kinfoPage->seq, seq));
|
||||
if (ret != EOK) {
|
||||
FFRT_SYSEVENT_LOGE("The memcpy operation failed for the infoArea.");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned int BlockawareLoadSnapshotNrRunningFast(unsigned long key, int domainId)
|
||||
{
|
||||
BlockawareKinfoPageS* kinfoPage = reinterpret_cast<BlockawareKinfoPageS*>(key);
|
||||
return kinfoPage->infoArea.localinfo[domainId].nrRunning;
|
||||
}
|
||||
|
||||
static inline unsigned int BlockawareLoadSnapshotNrBlockedFast(unsigned long key, int domainId)
|
||||
{
|
||||
BlockawareKinfoPageS* kinfoPage = reinterpret_cast<BlockawareKinfoPageS*>(key);
|
||||
return kinfoPage->infoArea.localinfo[domainId].nrBlocked;
|
||||
}
|
||||
|
||||
static inline int BlockawareWaitCond(struct BlockawareWakeupCond *cond)
|
||||
{
|
||||
int rc = prctl(HM_PR_SILK_BLOCKAWARE_OPS, BLOCKAWARE_SUBOPS_WAIT, reinterpret_cast<unsigned long>(cond));
|
||||
return (rc == 0) ? 0 : errno;
|
||||
}
|
||||
|
||||
static inline int BlockawareWake(void)
|
||||
{
|
||||
int rc = prctl(HM_PR_SILK_BLOCKAWARE_OPS, BLOCKAWARE_SUBOPS_WAKE);
|
||||
return (rc == 0) ? 0 : errno;
|
||||
}
|
||||
|
||||
static inline int BlockawareMonitorfd(int fd, struct BlockawareWakeupCond *cond)
|
||||
{
|
||||
int rc = prctl(HM_PR_SILK_BLOCKAWARE_OPS, BLOCKAWARE_SUBOPS_MONITORFD,
|
||||
static_cast<unsigned long>(fd), reinterpret_cast<unsigned long>(cond));
|
||||
return (rc >= 0) ? rc : -errno;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* BLOCKAWARE_H */
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 CO2_INT_H
|
||||
#define CO2_INT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "c/type_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__)
|
||||
#define FFRT_REG_NR 22
|
||||
#define FFRT_REG_LR 11
|
||||
#define FFRT_REG_SP 13
|
||||
#elif defined(__arm__)
|
||||
#define FFRT_REG_NR 64
|
||||
#define FFRT_REG_LR 1
|
||||
#define FFRT_REG_SP 0
|
||||
#elif defined(__x86_64__)
|
||||
#define FFRT_REG_NR 8
|
||||
#define FFRT_REG_LR 7
|
||||
#define FFRT_REG_SP 6
|
||||
#elif defined(__riscv) && __riscv_xlen == 64
|
||||
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/riscv/bits/setjmp.h;h=5dd7fa0120ab37c9ec5c4a854792c0935b9eddc1;hb=HEAD
|
||||
#if defined __riscv_float_abi_double
|
||||
#define FFRT_REG_NR 26
|
||||
#else
|
||||
#define FFRT_REG_NR 14
|
||||
#endif
|
||||
#define FFRT_REG_LR 0
|
||||
#define FFRT_REG_SP 13
|
||||
|
||||
#else
|
||||
#error "Unsupported architecture"
|
||||
#endif
|
||||
|
||||
int co2_save_context(ffrt_fiber_t* ctx);
|
||||
|
||||
void co2_restore_context(ffrt_fiber_t* ctx);
|
||||
|
||||
static inline void co2_switch_context(ffrt_fiber_t* from, ffrt_fiber_t* to)
|
||||
{
|
||||
if (co2_save_context(from) == 0) {
|
||||
co2_restore_context(to);
|
||||
}
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* CO2_INT_H */
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_CO_ROUTINE_HPP
|
||||
#define FFRT_CO_ROUTINE_HPP
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <pthread.h>
|
||||
#include "co2_context.h"
|
||||
|
||||
#if defined(__aarch64__)
|
||||
constexpr size_t STACK_MAGIC = 0x7BCDABCDABCDABCD;
|
||||
#elif defined(__arm__)
|
||||
constexpr size_t STACK_MAGIC = 0x7BCDABCD;
|
||||
#elif defined(__x86_64__)
|
||||
constexpr size_t STACK_MAGIC = 0x7BCDABCDABCDABCD;
|
||||
#endif
|
||||
|
||||
#ifndef FFRT_STACK_SIZE
|
||||
#define FFRT_STACK_SIZE (1 << 20)
|
||||
#endif
|
||||
|
||||
#ifdef ASAN_MODE
|
||||
extern "C" void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size);
|
||||
extern "C" void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old);
|
||||
extern "C" void __asan_handle_no_return();
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
class CoTask;
|
||||
class CPUEUTask;
|
||||
struct WaitEntry;
|
||||
} // namespace ffrt
|
||||
struct CoRoutine;
|
||||
|
||||
enum class CoStatus {
|
||||
CO_UNINITIALIZED,
|
||||
CO_NOT_FINISH,
|
||||
CO_RUNNING,
|
||||
};
|
||||
|
||||
enum class CoStackProtectType {
|
||||
CO_STACK_WEAK_PROTECT,
|
||||
CO_STACK_STRONG_PROTECT
|
||||
};
|
||||
|
||||
enum class CoWakeType {
|
||||
TIMEOUT_WAKE,
|
||||
NO_TIMEOUT_WAKE
|
||||
};
|
||||
|
||||
constexpr uint64_t STACK_SIZE = FFRT_STACK_SIZE;
|
||||
constexpr uint64_t MIN_STACK_SIZE = 32 * 1024;
|
||||
constexpr uint64_t STACK_MEM_SIZE = 8;
|
||||
|
||||
using CoCtx = ffrt_fiber_t;
|
||||
|
||||
struct CoRoutineEnv {
|
||||
// when task is running, runningCo same with task->co
|
||||
// if task switch out, set to null. if task complete, be used as co cache for next task.
|
||||
CoRoutine* runningCo = nullptr;
|
||||
CoCtx schCtx;
|
||||
const std::function<bool(ffrt::CoTask*)>* pending = nullptr;
|
||||
};
|
||||
|
||||
struct StackMem {
|
||||
uint64_t size;
|
||||
size_t magic;
|
||||
uint8_t stk[STACK_MEM_SIZE];
|
||||
};
|
||||
|
||||
struct CoRoutine {
|
||||
std::atomic_int status {static_cast<int>(CoStatus::CO_UNINITIALIZED)};
|
||||
CoRoutineEnv* thEnv;
|
||||
ffrt::CoTask* task;
|
||||
#ifdef ASAN_MODE
|
||||
void *asanFakeStack = nullptr; // not finished, need further verification
|
||||
const void *asanFiberAddr = nullptr;
|
||||
size_t asanFiberSize = 0;
|
||||
#endif
|
||||
CoCtx ctx;
|
||||
uint64_t allocatedSize; // CoRoutine allocated size
|
||||
bool isTaskDone = false;
|
||||
/* do not add item after stkMem */
|
||||
StackMem stkMem;
|
||||
};
|
||||
|
||||
struct CoStackAttr {
|
||||
public:
|
||||
explicit CoStackAttr(uint64_t coSize = STACK_SIZE, CoStackProtectType coType =
|
||||
CoStackProtectType::CO_STACK_WEAK_PROTECT)
|
||||
{
|
||||
size = coSize;
|
||||
type = coType;
|
||||
}
|
||||
~CoStackAttr() {}
|
||||
uint64_t size;
|
||||
CoStackProtectType type;
|
||||
|
||||
static inline CoStackAttr* Instance(uint64_t coSize = STACK_SIZE,
|
||||
CoStackProtectType coType = CoStackProtectType::CO_STACK_WEAK_PROTECT)
|
||||
{
|
||||
static CoStackAttr inst(coSize, coType);
|
||||
return &inst;
|
||||
}
|
||||
};
|
||||
|
||||
class CoRoutineFactory {
|
||||
public:
|
||||
using CowakeCB = std::function<void (ffrt::CoTask*, CoWakeType)>;
|
||||
|
||||
static CoRoutineFactory &Instance();
|
||||
|
||||
static void CoWakeFunc(ffrt::CoTask* task, CoWakeType type)
|
||||
{
|
||||
return Instance().cowake_(task, type);
|
||||
}
|
||||
|
||||
static void RegistCb(const CowakeCB &cowake)
|
||||
{
|
||||
Instance().cowake_ = cowake;
|
||||
}
|
||||
private:
|
||||
CowakeCB cowake_;
|
||||
};
|
||||
|
||||
void CoStackFree(void);
|
||||
void CoWorkerExit(void);
|
||||
|
||||
int CoStart(ffrt::CoTask* task, CoRoutineEnv* coRoutineEnv);
|
||||
void CoYield(void);
|
||||
|
||||
void CoWait(const std::function<bool(ffrt::CoTask*)>& pred);
|
||||
void CoWake(ffrt::CoTask* task, CoWakeType type);
|
||||
|
||||
CoRoutineEnv* GetCoEnv(void);
|
||||
|
||||
inline void* GetCoStackAddr(CoRoutine* co)
|
||||
{
|
||||
return static_cast<void*>(reinterpret_cast<char*>(co) + sizeof(CoRoutine) - STACK_MEM_SIZE);
|
||||
}
|
||||
|
||||
#ifdef FFRT_TASK_LOCAL_ENABLE
|
||||
void TaskTsdDeconstruct(ffrt::CPUEUTask* task);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 CO_ROUTINE_FACTORY_HPP
|
||||
#define CO_ROUTINE_FACTORY_HPP
|
||||
|
||||
#include "eu/co_routine.h"
|
||||
|
||||
namespace ffrt {
|
||||
|
||||
CoRoutine *CoRoutineAllocMem(std::size_t stack_size);
|
||||
void CoRoutineFreeMem(CoRoutine *co);
|
||||
void CoRoutineReleaseMem();
|
||||
void CoRoutineInstance(std::size_t size);
|
||||
|
||||
} // namespace ffrt
|
||||
|
||||
#endif
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_CPU_WORKER_HPP
|
||||
#define FFRT_CPU_WORKER_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <unistd.h>
|
||||
#ifdef FFRT_PTHREAD_ENABLE
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <thread>
|
||||
#ifdef OHOS_THREAD_STACK_DUMP
|
||||
#include <sstream>
|
||||
#endif
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
#include "tm/task_base.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
#include "c/executor_task.h"
|
||||
#include "util/spmc_queue.h"
|
||||
|
||||
namespace ffrt {
|
||||
constexpr int PTHREAD_CREATE_NO_MEM_CODE = 11;
|
||||
constexpr int FFRT_RETRY_MAX_COUNT = 12;
|
||||
const std::vector<uint64_t> FFRT_RETRY_CYCLE_LIST = {
|
||||
10 * 1000, 50 * 1000, 100 * 1000, 200 * 1000, 500 * 1000, 1000 * 1000, 2 * 1000 * 1000,
|
||||
5 * 1000 * 1000, 10 * 1000 * 1000, 50 * 1000 * 1000, 100 * 1000 * 1000, 500 * 1000 * 1000
|
||||
};
|
||||
|
||||
enum class WorkerAction {
|
||||
RETRY = 0,
|
||||
RETIRE,
|
||||
MAX,
|
||||
};
|
||||
|
||||
enum class WorkerStatus {
|
||||
EXECUTING = 0,
|
||||
SLEEPING,
|
||||
DESTROYED,
|
||||
};
|
||||
|
||||
class CPUWorker;
|
||||
struct CpuWorkerOps {
|
||||
std::function<WorkerAction (CPUWorker*)> WorkerIdleAction;
|
||||
std::function<void (CPUWorker*)> WorkerRetired;
|
||||
std::function<void (CPUWorker*)> WorkerPrepare;
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
std::function<bool (void)> IsBlockAwareInit;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CPUWorker {
|
||||
public:
|
||||
explicit CPUWorker(const QoS& qos, CpuWorkerOps&& ops, size_t stackSize);
|
||||
~CPUWorker();
|
||||
|
||||
bool Exited() const
|
||||
{
|
||||
return exited.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void SetExited()
|
||||
{
|
||||
exited.store(true, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
pid_t Id() const
|
||||
{
|
||||
while (!exited && tid < 0) {
|
||||
}
|
||||
return tid;
|
||||
}
|
||||
|
||||
const QoS& GetQos() const
|
||||
{
|
||||
return qos;
|
||||
}
|
||||
|
||||
const WorkerStatus& GetWorkerState() const
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
void SetWorkerState(const WorkerStatus& newState)
|
||||
{
|
||||
this->state = newState;
|
||||
}
|
||||
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
unsigned int GetDomainId() const
|
||||
{
|
||||
return domain_id;
|
||||
}
|
||||
#endif
|
||||
#ifdef FFRT_PTHREAD_ENABLE
|
||||
void Start(void*(*ThreadFunc)(void*), void* args)
|
||||
{
|
||||
int ret = pthread_create(&thread_, &attr_, ThreadFunc, args);
|
||||
if (ret == PTHREAD_CREATE_NO_MEM_CODE) {
|
||||
int count = 0;
|
||||
while (ret == PTHREAD_CREATE_NO_MEM_CODE && count < FFRT_RETRY_MAX_COUNT) {
|
||||
usleep(FFRT_RETRY_CYCLE_LIST[count]);
|
||||
count++;
|
||||
FFRT_LOGW("pthread_create failed due to shortage of system memory, FFRT retry %d times...", count);
|
||||
ret = pthread_create(&thread_, &attr_, ThreadFunc, args);
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
FFRT_LOGE("pthread_create failed, ret = %d", ret);
|
||||
exited = true;
|
||||
}
|
||||
pthread_attr_destroy(&attr_);
|
||||
}
|
||||
|
||||
void Join()
|
||||
{
|
||||
if (tid > 0 && thread_ != 0) {
|
||||
pthread_join(thread_, nullptr);
|
||||
}
|
||||
tid = -1;
|
||||
}
|
||||
|
||||
void Detach()
|
||||
{
|
||||
if (tid > 0 && thread_ != 0) {
|
||||
pthread_detach(thread_);
|
||||
} else {
|
||||
FFRT_LOGD("qos %d thread not joinable.", qos());
|
||||
}
|
||||
tid = -1;
|
||||
}
|
||||
|
||||
pthread_t& GetThread()
|
||||
{
|
||||
return this->thread_;
|
||||
}
|
||||
#else
|
||||
template <typename F, typename... Args>
|
||||
void Start(F&& f, Args&&... args)
|
||||
{
|
||||
auto wrap = [&](Args&&... args) {
|
||||
NativeConfig();
|
||||
return f(args...);
|
||||
};
|
||||
thread = std::thread(wrap, args...);
|
||||
}
|
||||
|
||||
void Join()
|
||||
{
|
||||
if (thread.joinable()) {
|
||||
thread.join();
|
||||
}
|
||||
tid = -1;
|
||||
}
|
||||
|
||||
void Detach()
|
||||
{
|
||||
if (thread.joinable()) {
|
||||
thread.detach();
|
||||
} else {
|
||||
FFRT_LOGD("qos %d thread not joinable\n", qos());
|
||||
}
|
||||
tid = -1;
|
||||
}
|
||||
|
||||
pthread_t GetThread()
|
||||
{
|
||||
return this->thread.native_handle();
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetThreadAttr(const QoS& newQos);
|
||||
TaskBase* curTask = nullptr;
|
||||
std::atomic<uintptr_t> curTaskType_ {ffrt_invalid_task};
|
||||
std::string curTaskLabel_ = ""; // 需要打开宏WORKER_CAHCE_NAMEID才会赋值
|
||||
uint64_t curTaskGid_ = UINT64_MAX;
|
||||
unsigned int tick = 0;
|
||||
|
||||
private:
|
||||
void NativeConfig();
|
||||
static void WorkerLooper(CPUWorker* worker);
|
||||
static void* WrapDispatch(void* worker);
|
||||
void WorkerSetup();
|
||||
static void Dispatch(CPUWorker* worker);
|
||||
static void RunTask(TaskBase* task, CPUWorker* worker);
|
||||
static bool RunSingleTask(int qos, CPUWorker *worker);
|
||||
#ifdef FFRT_SEND_EVENT
|
||||
int cacheQos; // cache int qos
|
||||
std::string cacheLabel; // cache string label
|
||||
uint64_t cacheFreq = 1000000; // cache cpu freq
|
||||
#endif
|
||||
std::atomic_bool exited {false};
|
||||
std::atomic<pid_t> tid {-1};
|
||||
QoS qos;
|
||||
CpuWorkerOps ops;
|
||||
WorkerStatus state {WorkerStatus::EXECUTING};
|
||||
#ifdef FFRT_PTHREAD_ENABLE
|
||||
pthread_t thread_{0};
|
||||
pthread_attr_t attr_;
|
||||
#else
|
||||
std::thread thread;
|
||||
#endif
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
unsigned int domain_id;
|
||||
#endif
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_EXECUTE_UNIT_HPP
|
||||
#define FFRT_EXECUTE_UNIT_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <condition_variable>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include "cpp/mutex.h"
|
||||
#include "sched/workgroup_internal.h"
|
||||
#include "eu/thread_group.h"
|
||||
#include "eu/cpu_worker.h"
|
||||
#include "sync/sync.h"
|
||||
#include "internal_inc/osal.h"
|
||||
#include "util/cb_func.h"
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
#include "eu/blockaware.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
constexpr uint64_t ONE_STAGE_INTERVAL = 10;
|
||||
constexpr uint64_t TWO_STAGE_INTERVAL = 100;
|
||||
constexpr uint64_t THREE_STAGE_INTERVAL = 1000;
|
||||
constexpr uint64_t ONE_STAGE_WORKER_NUM = 128;
|
||||
constexpr uint64_t TWO_STAGE_WORKER_NUM = 256;
|
||||
constexpr int DEEP_SLEEP_NUM_DOUBLE = 2;
|
||||
}
|
||||
|
||||
namespace ffrt {
|
||||
enum class TaskNotifyType {
|
||||
TASK_PICKED = 0,
|
||||
TASK_ADDED,
|
||||
TASK_LOCAL,
|
||||
TASK_ESCAPED,
|
||||
TASK_ADDED_RTQ,
|
||||
};
|
||||
|
||||
struct WorkerStatusInfo {
|
||||
unsigned int startedCnt = 0;
|
||||
unsigned int exitedCnt = 0;
|
||||
std::deque<pid_t> startedTids;
|
||||
std::deque<pid_t> exitedTids;
|
||||
};
|
||||
|
||||
struct CPUWorkerGroup {
|
||||
// rtg parameters
|
||||
std::unique_ptr<ThreadGroup> tg;
|
||||
uint64_t tgRefCount = 0;
|
||||
mutable std::shared_mutex tgMutex;
|
||||
|
||||
// worker manage parameters
|
||||
size_t hardLimit{0};
|
||||
size_t maxConcurrency{0};
|
||||
size_t workerStackSize{0};
|
||||
bool setWorkerMaxNum{false};
|
||||
std::unordered_map<CPUWorker *, std::unique_ptr<CPUWorker>> threads;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
|
||||
// group status parameters
|
||||
alignas(cacheline_size) fast_mutex lock;
|
||||
alignas(cacheline_size) int executingNum{0};
|
||||
alignas(cacheline_size) int sleepingNum{0};
|
||||
alignas(cacheline_size) bool irqEnable{false};
|
||||
/* used for performance mode */
|
||||
alignas(cacheline_size) bool fastWakeEnable = false; // directly wakeup first worker by futex
|
||||
alignas(cacheline_size) int pendingWakeCnt = 0; // number of workers waking but not waked-up yet
|
||||
alignas(cacheline_size) int pendingTaskCnt = 0; // number of tasks submitted to RTB but not picked-up yet
|
||||
|
||||
// used for worker share
|
||||
std::vector<std::pair<QoS, bool>> workerShareConfig;
|
||||
int deepSleepingWorkerNum{0};
|
||||
bool retryBeforeDeepSleep{true};
|
||||
|
||||
inline void WorkerCreate()
|
||||
{
|
||||
executingNum++;
|
||||
}
|
||||
|
||||
inline void RollBackCreate()
|
||||
{
|
||||
std::lock_guard lk(lock);
|
||||
executingNum--;
|
||||
}
|
||||
|
||||
inline void IntoDeepSleep()
|
||||
{
|
||||
std::lock_guard lk(lock);
|
||||
deepSleepingWorkerNum++;
|
||||
}
|
||||
|
||||
inline void OutOfDeepSleep(bool irqWake = false)
|
||||
{
|
||||
std::lock_guard lk(lock);
|
||||
if (irqWake) {
|
||||
irqEnable = false;
|
||||
}
|
||||
sleepingNum--;
|
||||
deepSleepingWorkerNum--;
|
||||
executingNum++;
|
||||
}
|
||||
|
||||
inline void OutOfSleep(bool irqWake = false)
|
||||
{
|
||||
std::lock_guard lk(lock);
|
||||
if (irqWake) {
|
||||
irqEnable = false;
|
||||
}
|
||||
if (pendingWakeCnt > 0) {
|
||||
pendingWakeCnt--;
|
||||
}
|
||||
sleepingNum--;
|
||||
executingNum++;
|
||||
}
|
||||
|
||||
inline void WorkerDestroy()
|
||||
{
|
||||
std::lock_guard lk(lock);
|
||||
sleepingNum--;
|
||||
}
|
||||
|
||||
inline bool TryDestroy()
|
||||
{
|
||||
std::lock_guard lk(lock);
|
||||
sleepingNum--;
|
||||
return sleepingNum > 0;
|
||||
}
|
||||
|
||||
inline void RollbackDestroy(bool irqWake = false)
|
||||
{
|
||||
std::lock_guard lk(lock);
|
||||
if (irqWake) {
|
||||
irqEnable = false;
|
||||
}
|
||||
executingNum++;
|
||||
}
|
||||
|
||||
inline void SetTearDown()
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lck(tgMutex);
|
||||
for (const auto& pair : threads) {
|
||||
pair.second->SetExited();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct EscapeConfig {
|
||||
bool enableEscape_ = false;
|
||||
uint64_t oneStageIntervalMs_ = ONE_STAGE_INTERVAL;
|
||||
uint64_t twoStageIntervalMs_ = TWO_STAGE_INTERVAL;
|
||||
uint64_t threeStageIntervalMs_ = THREE_STAGE_INTERVAL;
|
||||
uint64_t oneStageWorkerNum_ = ONE_STAGE_WORKER_NUM;
|
||||
uint64_t twoStageWorkerNum_ = TWO_STAGE_WORKER_NUM;
|
||||
};
|
||||
|
||||
class ExecuteUnit {
|
||||
public:
|
||||
static ExecuteUnit &Instance();
|
||||
|
||||
static void RegistInsCb(SingleInsCB<ExecuteUnit>::Instance &&cb);
|
||||
|
||||
ThreadGroup *BindTG(QoS& qos);
|
||||
void UnbindTG(QoS& qos);
|
||||
void BindWG(QoS& qos);
|
||||
|
||||
// event notify
|
||||
template <TaskNotifyType TYPE>
|
||||
void NotifyTask(const QoS &qos, bool isPollWait = false, bool isRisingEdge = false)
|
||||
{
|
||||
if constexpr (TYPE == TaskNotifyType::TASK_ADDED) {
|
||||
PokeAdd(qos);
|
||||
} else if constexpr (TYPE == TaskNotifyType::TASK_PICKED) {
|
||||
PokePick(qos);
|
||||
} else if constexpr (TYPE == TaskNotifyType::TASK_ESCAPED) {
|
||||
PokeEscape(qos, isPollWait);
|
||||
} else if constexpr (TYPE == TaskNotifyType::TASK_LOCAL) {
|
||||
PokeLocal(qos);
|
||||
} else if constexpr (TYPE == TaskNotifyType::TASK_ADDED_RTQ) {
|
||||
PokeAddRtq(qos, isRisingEdge);
|
||||
}
|
||||
}
|
||||
|
||||
// dfx op
|
||||
virtual void WorkerInit() = 0;
|
||||
CPUWorkerGroup &GetWorkerGroup(int qos)
|
||||
{
|
||||
return workerGroup[qos];
|
||||
}
|
||||
|
||||
inline int SetWorkerMaxNum(const QoS &qos, uint32_t num)
|
||||
{
|
||||
CPUWorkerGroup &group = workerGroup[qos];
|
||||
std::lock_guard lk(group.lock);
|
||||
if (group.setWorkerMaxNum) {
|
||||
FFRT_SYSEVENT_LOGE("qos[%d] worker num can only been setup once", qos());
|
||||
return -1;
|
||||
}
|
||||
group.hardLimit = static_cast<size_t>(num);
|
||||
group.setWorkerMaxNum = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SetWorkerStackSize(const QoS &qos, size_t stack_size);
|
||||
|
||||
// worker escape
|
||||
int SetEscapeEnable(uint64_t oneStageIntervalMs, uint64_t twoStageIntervalMs, uint64_t threeStageIntervalMs,
|
||||
uint64_t oneStageWorkerNum, uint64_t twoStageWorkerNum);
|
||||
|
||||
inline void SetEscapeDisable()
|
||||
{
|
||||
escapeConfig.enableEscape_ = false;
|
||||
// after the escape function is disabled, parameters are restored to default values
|
||||
escapeConfig.oneStageIntervalMs_ = ONE_STAGE_INTERVAL;
|
||||
escapeConfig.twoStageIntervalMs_ = TWO_STAGE_INTERVAL;
|
||||
escapeConfig.threeStageIntervalMs_ = THREE_STAGE_INTERVAL;
|
||||
escapeConfig.oneStageWorkerNum_ = ONE_STAGE_WORKER_NUM;
|
||||
escapeConfig.twoStageWorkerNum_ = TWO_STAGE_WORKER_NUM;
|
||||
}
|
||||
|
||||
inline bool IsEscapeEnable()
|
||||
{
|
||||
return escapeConfig.enableEscape_;
|
||||
}
|
||||
|
||||
void SubmitEscape(int qos, uint64_t totalWorkerNum);
|
||||
|
||||
inline uint64_t GetWorkerNum()
|
||||
{
|
||||
return workerNum.load();
|
||||
}
|
||||
|
||||
inline void SetSchedMode(const QoS qos, const sched_mode_type mode)
|
||||
{
|
||||
schedMode[qos].store(mode);
|
||||
}
|
||||
|
||||
inline sched_mode_type GetSchedMode(const QoS qos)
|
||||
{
|
||||
return schedMode[qos].load();
|
||||
}
|
||||
|
||||
inline void SetWorkerShare(const std::map<QoS, std::vector<std::pair<QoS, bool>>> workerShareConfig)
|
||||
{
|
||||
for (const auto& item : workerShareConfig) {
|
||||
workerGroup[item.first].workerShareConfig = item.second;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetTaskBacklog(const std::set<QoS> userTaskBacklogConfig)
|
||||
{
|
||||
for (const QoS& qos : userTaskBacklogConfig) {
|
||||
taskBacklogConfig[qos] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreThreadConfig();
|
||||
|
||||
void NotifyWorkers(const QoS &qos, int number);
|
||||
// used for worker sharing
|
||||
bool WorkerShare(CPUWorker* worker, std::function<bool(int, CPUWorker*)> taskFunction);
|
||||
// worker dynamic scaling
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
void MonitorMain();
|
||||
BlockawareWakeupCond *WakeupCond(void);
|
||||
#endif
|
||||
void WorkerStart(int qos);
|
||||
void WorkerExit(int qos);
|
||||
WorkerStatusInfo GetWorkerStatusInfoAndReset(int qos);
|
||||
|
||||
protected:
|
||||
virtual void WakeupWorkers(const QoS &qos) = 0;
|
||||
|
||||
// worker manipulate op
|
||||
bool IncWorker(const QoS &qos);
|
||||
virtual void WorkerPrepare(CPUWorker *thread) = 0;
|
||||
virtual WorkerAction WorkerIdleAction(CPUWorker *thread) = 0;
|
||||
void WorkerRetired(CPUWorker *thread);
|
||||
|
||||
// worker rtg config
|
||||
void WorkerJoinTg(const QoS &qos, pid_t pid);
|
||||
void WorkerLeaveTg(const QoS &qos, pid_t pid);
|
||||
|
||||
// worker group info
|
||||
inline bool IsExceedDeepSleepThreshold()
|
||||
{
|
||||
int totalWorker = 0;
|
||||
int deepSleepingWorkerNum = 0;
|
||||
for (unsigned int i = 0; i < static_cast<unsigned int>(QoS::Max()); i++) {
|
||||
CPUWorkerGroup &group = workerGroup[i];
|
||||
std::lock_guard lk(group.lock);
|
||||
deepSleepingWorkerNum += group.deepSleepingWorkerNum;
|
||||
totalWorker += group.executingNum + group.sleepingNum;
|
||||
}
|
||||
return deepSleepingWorkerNum * DEEP_SLEEP_NUM_DOUBLE > totalWorker;
|
||||
}
|
||||
|
||||
// worker group state
|
||||
virtual void IntoSleep(const QoS &qos) = 0;
|
||||
|
||||
ExecuteUnit();
|
||||
virtual ~ExecuteUnit();
|
||||
|
||||
size_t GetRunningNum(const QoS &qos);
|
||||
void ReportEscapeEvent(int qos, size_t totalNum);
|
||||
|
||||
CPUWorkerGroup workerGroup[QoS::MaxNum()];
|
||||
std::atomic_uint64_t workerNum = 0;
|
||||
std::atomic_bool tearDown{false};
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
bool blockAwareInit{false};
|
||||
bool stopMonitor{false};
|
||||
unsigned long keyPtr{0};
|
||||
int qosMonitorMaxNum{std::min(QoS::Max(), BLOCKAWARE_DOMAIN_ID_MAX + 1)};
|
||||
BlockawareWakeupCond wakeupCond;
|
||||
BlockawareDomainInfoArea domainInfoMonitor;
|
||||
#endif
|
||||
|
||||
// eu sched task bacllog array
|
||||
bool taskBacklogConfig[QoS::MaxNum()] = {};
|
||||
private:
|
||||
CPUWorker *CreateCPUWorker(const QoS &qos);
|
||||
|
||||
virtual void PokeAdd(const QoS &qos) = 0;
|
||||
virtual void PokePick(const QoS &qos) = 0;
|
||||
virtual void PokeLocal(const QoS &qos) = 0;
|
||||
virtual void PokeEscape(const QoS &qos, bool isPollWait) = 0;
|
||||
virtual void PokeAddRtq(const QoS &qos, bool isRisingEdge) = 0;
|
||||
|
||||
// eu sched mode array
|
||||
static std::array<std::atomic<sched_mode_type>, QoS::MaxNum()> schedMode;
|
||||
|
||||
// worker escape
|
||||
EscapeConfig escapeConfig;
|
||||
std::atomic<bool> submittedDelayedTask_[QoS::MaxNum()] = {0};
|
||||
WaitUntilEntry *we_[QoS::MaxNum()] = {nullptr};
|
||||
virtual void ExecuteEscape(int qos) = 0;
|
||||
|
||||
inline uint64_t CalEscapeInterval(uint64_t totalWorkerNum)
|
||||
{
|
||||
if (totalWorkerNum < escapeConfig.oneStageWorkerNum_) {
|
||||
return escapeConfig.oneStageIntervalMs_;
|
||||
} else if (totalWorkerNum >= escapeConfig.oneStageWorkerNum_ &&
|
||||
totalWorkerNum < escapeConfig.twoStageWorkerNum_) {
|
||||
return escapeConfig.twoStageIntervalMs_;
|
||||
} else {
|
||||
return escapeConfig.threeStageIntervalMs_;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
bool IsBlockAwareInit(void);
|
||||
#endif
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_FUNC_MANAGER_HPP
|
||||
#define FFRT_FUNC_MANAGER_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
#include "ffrt_inner.h"
|
||||
#include "c/executor_task.h"
|
||||
|
||||
namespace ffrt {
|
||||
class FuncManager {
|
||||
public:
|
||||
FuncManager(const FuncManager&) = delete;
|
||||
FuncManager& operator=(const FuncManager&) = delete;
|
||||
~FuncManager()
|
||||
{
|
||||
}
|
||||
|
||||
// 获取FuncManager的单例
|
||||
static inline FuncManager* Instance()
|
||||
{
|
||||
static FuncManager func_mg;
|
||||
return &func_mg;
|
||||
}
|
||||
|
||||
void insert(ffrt_executor_task_type_t type, ffrt_executor_task_func func)
|
||||
{
|
||||
func_map[type] = func;
|
||||
}
|
||||
|
||||
ffrt_executor_task_func getFunc(ffrt_executor_task_type_t type)
|
||||
{
|
||||
if (func_map.find(type) == func_map.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return func_map[type];
|
||||
}
|
||||
|
||||
private:
|
||||
FuncManager()
|
||||
{
|
||||
func_map[ffrt_io_task] = nullptr;
|
||||
func_map[ffrt_uv_task] = nullptr;
|
||||
}
|
||||
std::unordered_map<ffrt_executor_task_type_t, ffrt_executor_task_func> func_map;
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 FFRT_POLLER_MANAGER_H
|
||||
#define FFRT_POLLER_MANAGER_H
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#endif
|
||||
#include <list>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
#include "sync/sync.h"
|
||||
#include "internal_inc/non_copyable.h"
|
||||
#include "c/executor_task.h"
|
||||
#include "sync/poller.h"
|
||||
#include "tm/task_base.h"
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
#include "dfx/trace/ffrt_trace_chain.h"
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
enum class PollerState {
|
||||
HANDLING, // worker执行事件回调(如果是同步回调函数执行有可能阻塞worker)
|
||||
POLLING, // worker处于epoll_wait睡眠(事件响应)
|
||||
EXITED, // worker没有事件时销毁线程(重新注册时触发创建线程)
|
||||
};
|
||||
|
||||
// 根据历史继承的能力
|
||||
enum class PollerType {
|
||||
WAKEUP,
|
||||
SYNC_IO,
|
||||
ASYNC_CB,
|
||||
ASYNC_IO,
|
||||
};
|
||||
|
||||
struct WakeData {
|
||||
WakeData() {}
|
||||
WakeData(int fdVal, CoTask *taskVal) : fd(fdVal), task(taskVal)
|
||||
{
|
||||
mode = PollerType::SYNC_IO;
|
||||
}
|
||||
WakeData(int fdVal, void *dataVal, std::function<void(void *, uint32_t)> cbVal, CoTask *taskVal)
|
||||
: fd(fdVal), data(dataVal), cb(cbVal), task(taskVal)
|
||||
{
|
||||
if (cb == nullptr) {
|
||||
mode = PollerType::ASYNC_IO;
|
||||
} else {
|
||||
mode = PollerType::ASYNC_CB;
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
if (TraceChainAdapter::Instance().HiTraceChainGetId().valid == HITRACE_ID_VALID) {
|
||||
traceId = TraceChainAdapter::Instance().HiTraceChainCreateSpan();
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
PollerType mode;
|
||||
int fd = 0;
|
||||
void* data = nullptr;
|
||||
std::function<void(void*, uint32_t)> cb = nullptr;
|
||||
CoTask* task = nullptr;
|
||||
uint32_t monitorEvents = 0;
|
||||
HiTraceIdStruct traceId;
|
||||
};
|
||||
|
||||
struct TimeOutReport {
|
||||
TimeOutReport() {}
|
||||
std::atomic<uint64_t> cbStartTime = 0; // block info report
|
||||
uint64_t reportCount = 0;
|
||||
};
|
||||
|
||||
using EventVec = typename std::vector<epoll_event>;
|
||||
class IOPoller : private NonCopyable {
|
||||
static constexpr int EPOLL_EVENT_SIZE = 1024;
|
||||
using WakeDataList = typename std::list<std::unique_ptr<struct WakeData>>;
|
||||
public:
|
||||
static IOPoller& Instance();
|
||||
~IOPoller() noexcept;
|
||||
|
||||
int AddFdEvent(int op, uint32_t events, int fd, void* data, ffrt_poller_cb cb) noexcept;
|
||||
int DelFdEvent(int fd) noexcept;
|
||||
int WaitFdEvent(struct epoll_event *eventsVec, int maxevents, int timeout) noexcept;
|
||||
void WaitFdEvent(int fd) noexcept;
|
||||
|
||||
inline uint64_t GetPollCount() noexcept
|
||||
{
|
||||
return pollerCount_;
|
||||
}
|
||||
|
||||
inline uint64_t GetTaskWaitTime(CoTask* task) noexcept
|
||||
{
|
||||
std::lock_guard lock(m_mapMutex);
|
||||
auto iter = m_waitTaskMap.find(task);
|
||||
if (iter == m_waitTaskMap.end()) {
|
||||
return 0;
|
||||
}
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||
iter->second.waitTP.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
inline void ClearCachedEvents(CoTask* task) noexcept
|
||||
{
|
||||
std::lock_guard lock(m_mapMutex);
|
||||
auto iter = m_cachedTaskEvents.find(task);
|
||||
if (iter == m_cachedTaskEvents.end()) {
|
||||
return;
|
||||
}
|
||||
m_cachedTaskEvents.erase(iter);
|
||||
ClearMaskWakeDataCache(task);
|
||||
}
|
||||
|
||||
void WakeUp() noexcept;
|
||||
void WakeTimeoutTask(CoTask* task) noexcept;
|
||||
void MonitTimeOut();
|
||||
|
||||
private:
|
||||
IOPoller() noexcept;
|
||||
|
||||
void ThreadInit();
|
||||
void Run();
|
||||
int PollOnce(int timeout = -1) noexcept;
|
||||
|
||||
void ReleaseFdWakeData() noexcept;
|
||||
void WakeSyncTask(std::unordered_map<CoTask*, EventVec>& syncTaskEvents) noexcept;
|
||||
|
||||
void CacheEventsAndDoMask(CoTask* task, EventVec& eventVec) noexcept;
|
||||
int FetchCachedEventAndDoUnmask(CoTask* task, struct epoll_event* eventsVec) noexcept;
|
||||
int FetchCachedEventAndDoUnmask(EventVec& cachedEventsVec, struct epoll_event* eventsVec) noexcept;
|
||||
void CacheMaskFdAndEpollDel(int fd, CoTask *task) noexcept;
|
||||
int ClearMaskWakeDataCache(CoTask *task) noexcept;
|
||||
int ClearMaskWakeDataCacheWithFd(CoTask *task, int fd) noexcept;
|
||||
int ClearDelFdCache(int fd) noexcept;
|
||||
|
||||
int m_epFd; // epoll fd
|
||||
struct WakeData m_wakeData; // self wakeup fd
|
||||
mutable spin_mutex m_mapMutex;
|
||||
struct TimeOutReport timeOutReport;
|
||||
|
||||
std::atomic_uint64_t m_syncFdCnt { 0 }; // record sync fd counts
|
||||
// record async fd and events
|
||||
std::unordered_map<int, WakeDataList> m_wakeDataMap;
|
||||
std::unordered_map<int, int> m_delCntMap;
|
||||
std::unordered_map<CoTask*, SyncData> m_waitTaskMap;
|
||||
std::unordered_map<CoTask*, EventVec> m_cachedTaskEvents;
|
||||
std::unordered_map<int, CoTask*> m_delFdCacheMap;
|
||||
std::unordered_map<CoTask*, WakeDataList> m_maskWakeDataMap;
|
||||
|
||||
std::unique_ptr<std::thread> m_runner { nullptr }; // ffrt_io_poller thread
|
||||
bool m_exitFlag { true }; // thread exit
|
||||
bool m_teardown { false }; // process teardown
|
||||
std::atomic<uint64_t> pollerCount_ { 0 };
|
||||
std::atomic<PollerState> m_state { PollerState::EXITED }; // worker state
|
||||
|
||||
std::array<queue*, QoS::MaxNum()> workQue; // queue(per qos) for execute async cb
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 QOS_INTERFACE_H
|
||||
#define QOS_INTERFACE_H
|
||||
#include "internal_inc/config.h"
|
||||
#include "eu/cpu_worker.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* generic
|
||||
*/
|
||||
#define SYSTEM_UID 1000
|
||||
#define ROOT_UID 0
|
||||
|
||||
/*
|
||||
* auth_ctrl
|
||||
*/
|
||||
struct AuthCtrlData {
|
||||
unsigned int uid;
|
||||
unsigned int type;
|
||||
unsigned int rtgUaFlag;
|
||||
unsigned int qosUaFlag;
|
||||
unsigned int status;
|
||||
};
|
||||
|
||||
enum AuthManipulateType {
|
||||
AUTH_ENABLE = 1,
|
||||
AUTH_DELETE,
|
||||
AUTH_GET,
|
||||
AUTH_SWITCH,
|
||||
AUTH_MAX_NR,
|
||||
};
|
||||
|
||||
enum AuthStatus {
|
||||
AUTH_STATUS_DISABLED = 1,
|
||||
AUTH_STATUS_SYSTEM_SERVER = 2,
|
||||
AUTH_STATUS_FOREGROUND = 3,
|
||||
AUTH_STATUS_BACKGROUND = 4,
|
||||
AUTH_STATUS_DEAD,
|
||||
};
|
||||
|
||||
enum AuthCtrlCmdid {
|
||||
BASIC_AUTH_CTRL = 1,
|
||||
AUTH_CTRL_MAX_NR
|
||||
};
|
||||
|
||||
#define AUTH_CTRL_IPC_MAGIG 0xCD
|
||||
|
||||
#define BASIC_AUTH_CTRL_OPERATION \
|
||||
_IOWR(AUTH_CTRL_IPC_MAGIG, BASIC_AUTH_CTRL, struct AuthCtrlData)
|
||||
|
||||
/*
|
||||
* qos ctrl
|
||||
*/
|
||||
constexpr unsigned char QOS_NUM_MAX = 10;
|
||||
|
||||
constexpr unsigned char AF_QOS_ALL = 0x0003;
|
||||
constexpr unsigned char AF_QOS_DELEGATED = 0x0001;
|
||||
|
||||
enum QosManipulateType {
|
||||
QOS_APPLY = 1,
|
||||
QOS_LEAVE,
|
||||
QOS_GET,
|
||||
QOS_MAX_NR,
|
||||
};
|
||||
|
||||
struct QosCtrlData {
|
||||
int pid;
|
||||
unsigned int type;
|
||||
unsigned int level;
|
||||
int qos;
|
||||
int staticQos;
|
||||
int dynamicQos;
|
||||
int tagSchedEnable = false;
|
||||
};
|
||||
|
||||
struct QosPolicyData {
|
||||
int latency_nice;
|
||||
int uclamp_min;
|
||||
int uclamp_max;
|
||||
unsigned long affinity;
|
||||
unsigned char priority;
|
||||
unsigned char init_load;
|
||||
unsigned char prefer_idle;
|
||||
};
|
||||
|
||||
constexpr unsigned char THREAD_CTRL_NUM = 4;
|
||||
|
||||
struct ThreadAttrCtrl {
|
||||
int tid;
|
||||
bool prioritySetEnable;
|
||||
bool affinitySetEnable;
|
||||
};
|
||||
|
||||
struct ThreadAttrCtrlDatas {
|
||||
struct ThreadAttrCtrl ctrls[THREAD_CTRL_NUM];
|
||||
};
|
||||
|
||||
enum QosPolicyType {
|
||||
QOS_POLICY_DEFAULT = 1,
|
||||
QOS_POLICY_SYSTEM_SERVER = 2,
|
||||
QOS_POLICY_FRONT = 3,
|
||||
QOS_POLICY_BACK = 4,
|
||||
QOS_POLICY_MAX_NR,
|
||||
};
|
||||
|
||||
constexpr unsigned char QOS_FLAG_NICE = 0X01;
|
||||
constexpr unsigned char QOS_FLAG_LATENCY_NICE = 0X02;
|
||||
constexpr unsigned char QOS_FLAG_UCLAMP = 0x04;
|
||||
constexpr unsigned char QOS_FLAG_RT = 0x08;
|
||||
|
||||
#define QOS_FLAG_ALL (QOS_FLAG_NICE | \
|
||||
QOS_FLAG_LATENCY_NICE | \
|
||||
QOS_FLAG_UCLAMP | \
|
||||
QOS_FLAG_RT)
|
||||
|
||||
struct QosPolicyDatas {
|
||||
int policyType;
|
||||
unsigned int policyFlag;
|
||||
struct QosPolicyData policys[NR_QOS + 1];
|
||||
};
|
||||
|
||||
enum QosCtrlCmdid {
|
||||
QOS_CTRL = 1,
|
||||
QOS_POLICY,
|
||||
QOS_THREAD_CTRL,
|
||||
QOS_CTRL_MAX_NR
|
||||
};
|
||||
|
||||
#define QOS_CTRL_IPC_MAGIG 0xCC
|
||||
|
||||
#define QOS_CTRL_BASIC_OPERATION \
|
||||
_IOWR(QOS_CTRL_IPC_MAGIG, QOS_CTRL, struct QosCtrlData)
|
||||
#define QOS_CTRL_POLICY_OPERATION \
|
||||
_IOWR(QOS_CTRL_IPC_MAGIG, QOS_POLICY, struct QosPolicyDatas)
|
||||
#define QOS_THREAD_CTRL_OPERATION \
|
||||
_IOWR(QOS_CTRL_IPC_MAGIG, QOS_THREAD_CTRL, struct ThreadAttrCtrl)
|
||||
|
||||
/*
|
||||
* RTG
|
||||
*/
|
||||
#define AF_RTG_ALL 0x1fff
|
||||
#define AF_RTG_DELEGATED 0x1fff
|
||||
|
||||
struct RtgEnableData {
|
||||
int enable;
|
||||
size_t len;
|
||||
char *data;
|
||||
};
|
||||
|
||||
enum RtgSchedCmdid {
|
||||
SET_ENABLE = 1,
|
||||
SET_RTG,
|
||||
SET_CONFIG,
|
||||
SET_RTG_ATTR,
|
||||
BEGIN_FRAME_FREQ = 5,
|
||||
END_FRAME_FREQ,
|
||||
END_SCENE,
|
||||
SET_MIN_UTIL,
|
||||
SET_MARGIN,
|
||||
LIST_RTG = 10,
|
||||
LIST_RTG_THREAD,
|
||||
SEARCH_RTG,
|
||||
GET_ENABLE,
|
||||
RTG_CTRL_MAX_NR,
|
||||
};
|
||||
|
||||
#define RTG_SCHED_IPC_MAGIC 0xAB
|
||||
|
||||
#define CMD_ID_SET_ENABLE \
|
||||
_IOWR(RTG_SCHED_IPC_MAGIC, SET_ENABLE, struct RtgEnableData)
|
||||
|
||||
/*
|
||||
* interface
|
||||
*/
|
||||
int FFRTEnableRtg(bool flag);
|
||||
int FFRTAuthEnable(unsigned int uid, unsigned int uaFlag, unsigned int status);
|
||||
int FFRTAuthPause(unsigned int uid);
|
||||
int FFRTAuthDelete(unsigned int uid);
|
||||
int FFRTAuthGet(unsigned int uid, unsigned int *uaFlag, unsigned int *status);
|
||||
int FFRTAuthSwitch(unsigned int uid, unsigned int rtgFlag, unsigned int qosFlag, unsigned int status);
|
||||
int FFRTQosApply(unsigned int level);
|
||||
int FFRTQosApplyForOther(unsigned int level, int tid);
|
||||
int FFRTQosLeave(void);
|
||||
int FFRTQosLeaveForOther(int tid);
|
||||
int FFRTQosGet(struct QosCtrlData &data);
|
||||
int FFRTQosGetForOther(int tid, struct QosCtrlData &data);
|
||||
int QosPolicy(struct QosPolicyDatas *policyDatas);
|
||||
int ThreadCtrl(int tid, struct ThreadAttrCtrl &ctrlDatas);
|
||||
typedef int (*Func_affinity)(unsigned long affinity, int tid);
|
||||
void setFuncAffinity(Func_affinity func);
|
||||
Func_affinity getFuncAffinity(void);
|
||||
typedef void (*Func_priority)(unsigned char priority, ffrt::CPUWorker* thread);
|
||||
void setFuncPriority(Func_priority func);
|
||||
Func_priority getFuncPriority(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OQS_INTERFACE_H */
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_RTG_IOCTL_H
|
||||
#define FFRT_RTG_IOCTL_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
namespace ffrt {
|
||||
struct RTGLoadInfo {
|
||||
uint64_t load = 0;
|
||||
uint64_t runtime = 0;
|
||||
};
|
||||
|
||||
class RTGCtrl {
|
||||
class RTGMsg;
|
||||
|
||||
public:
|
||||
static RTGCtrl& Instance()
|
||||
{
|
||||
static RTGCtrl ctrl;
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
bool Enabled() const
|
||||
{
|
||||
return fd >= 0;
|
||||
}
|
||||
|
||||
int GetThreadGroup();
|
||||
bool PutThreadGroup(int tgid);
|
||||
bool JoinThread(int tgid, pid_t tid);
|
||||
bool RemoveThread(int tgid, pid_t tid);
|
||||
bool UpdatePerfUtil(int tgid, int util);
|
||||
bool UpdatePerfFreq(int tgid, int64_t freq);
|
||||
RTGLoadInfo UpdateAndGetLoad(int tgid, pid_t tid);
|
||||
RTGLoadInfo UpdateAndGetLoad(int tgid);
|
||||
bool SetGroupWindowSize(int tgid, uint64_t size);
|
||||
bool SetInvalidInterval(int tgid, uint64_t interval);
|
||||
|
||||
bool Begin(int tgid);
|
||||
bool End(int tgid);
|
||||
|
||||
bool SetPreferredCluster(int tgid, int clusterId);
|
||||
|
||||
static pid_t GetTID();
|
||||
|
||||
private:
|
||||
RTGCtrl();
|
||||
~RTGCtrl();
|
||||
|
||||
bool RTGIOCtrl(RTGMsg& msg);
|
||||
|
||||
int fd = -1;
|
||||
};
|
||||
}; // namespace ffrt
|
||||
|
||||
#endif
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_SEXECUTE_UNIT_HPP
|
||||
#define FFRT_SEXECUTE_UNIT_HPP
|
||||
|
||||
#include "execute_unit.h"
|
||||
#include "util/ffrt_facade.h"
|
||||
|
||||
namespace ffrt {
|
||||
class SExecuteUnit : public ExecuteUnit {
|
||||
public:
|
||||
static SExecuteUnit& Instance()
|
||||
{
|
||||
static SExecuteUnit ins;
|
||||
return ins;
|
||||
}
|
||||
|
||||
void WorkerInit() override {}
|
||||
|
||||
void WorkerPrepare(CPUWorker* thread) override
|
||||
{
|
||||
WorkerJoinTg(thread->GetQos(), thread->Id());
|
||||
}
|
||||
|
||||
WorkerAction WorkerIdleAction(CPUWorker* thread) override;
|
||||
|
||||
void WakeupWorkers(const QoS& qos) override;
|
||||
|
||||
void IntoSleep(const QoS& qos) override
|
||||
{
|
||||
CPUWorkerGroup& group = workerGroup[qos];
|
||||
std::lock_guard lg(group.lock);
|
||||
group.sleepingNum++;
|
||||
group.executingNum--;
|
||||
}
|
||||
|
||||
/* strategy options for handling task notify events */
|
||||
static void HandleTaskNotifyDefault(SExecuteUnit* manager, const QoS& qos, TaskNotifyType notifyType);
|
||||
static void HandleTaskNotifyConservative(SExecuteUnit* manager, const QoS& qos, TaskNotifyType notifyType);
|
||||
static void HandleTaskNotifyUltraConservative(SExecuteUnit* manager, const QoS& qos, TaskNotifyType notifyType);
|
||||
private:
|
||||
SExecuteUnit();
|
||||
~SExecuteUnit() override;
|
||||
|
||||
void PokeAdd(const QoS& qos) override
|
||||
{
|
||||
handleTaskNotify(this, qos, TaskNotifyType::TASK_ADDED);
|
||||
}
|
||||
void PokePick(const QoS& qos) override
|
||||
{
|
||||
handleTaskNotify(this, qos, TaskNotifyType::TASK_PICKED);
|
||||
}
|
||||
void PokeLocal(const QoS& qos) override
|
||||
{
|
||||
if (FFRTFacade::GetSchedInstance()->GetScheduler(qos).stealWorkers.load(std::memory_order_relaxed) == 0) {
|
||||
handleTaskNotify(this, qos, TaskNotifyType::TASK_LOCAL);
|
||||
}
|
||||
}
|
||||
void PokeEscape(const QoS& qos, bool isPollWait) override
|
||||
{
|
||||
handleTaskNotify(this, qos, TaskNotifyType::TASK_ESCAPED);
|
||||
}
|
||||
|
||||
void PokeAddRtq(const QoS &qos, bool isRisingEdge) override
|
||||
{
|
||||
(void)isRisingEdge; // deprecated
|
||||
handleTaskNotify(this, qos, TaskNotifyType::TASK_ADDED);
|
||||
}
|
||||
|
||||
void PokeImpl(const QoS& qos, uint32_t taskCount, TaskNotifyType notifyType);
|
||||
void ExecuteEscape(int qos) override;
|
||||
|
||||
std::function<void (SExecuteUnit*, const QoS&, TaskNotifyType)> handleTaskNotify { nullptr };
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_THREAD_GROUP_H
|
||||
#define FFRT_THREAD_GROUP_H
|
||||
|
||||
#include "eu/rtg_ioctl.h"
|
||||
|
||||
namespace ffrt {
|
||||
class ThreadGroup {
|
||||
public:
|
||||
int Id() const
|
||||
{
|
||||
return tgid;
|
||||
}
|
||||
|
||||
bool Enabled() const
|
||||
{
|
||||
return tgid >= 0 && RTGCtrl::Instance().Enabled();
|
||||
}
|
||||
|
||||
bool Init()
|
||||
{
|
||||
if (Enabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
tgid = RTGCtrl::Instance().GetThreadGroup();
|
||||
return tgid >= 0;
|
||||
}
|
||||
|
||||
bool Release()
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!RTGCtrl::Instance().PutThreadGroup(tgid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tgid = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
if (!Enabled() || isBegin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
isbegin = true;
|
||||
RTGCtrl::Instance().Begin(tgid);
|
||||
}
|
||||
|
||||
void End()
|
||||
{
|
||||
if (!Enabled() || !isBegin()) {
|
||||
return;
|
||||
}
|
||||
RTGCtrl::Instance().End(tgid);
|
||||
isbegin = false;
|
||||
}
|
||||
|
||||
bool Join()
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().JoinThread(tgid, RTGCtrl::GetTID());
|
||||
}
|
||||
|
||||
bool Join(pid_t tid)
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().JoinThread(tgid, tid);
|
||||
}
|
||||
|
||||
bool Leave()
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().RemoveThread(tgid, RTGCtrl::GetTID());
|
||||
}
|
||||
|
||||
bool Leave(pid_t tid)
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().RemoveThread(tgid, tid);
|
||||
}
|
||||
|
||||
bool UpdateFreq(int64_t freq)
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().UpdatePerfFreq(tgid, freq);
|
||||
}
|
||||
|
||||
bool UpdateUitl(int64_t util)
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().UpdatePerfUtil(tgid, util);
|
||||
}
|
||||
|
||||
RTGLoadInfo GetLoad()
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return RTGLoadInfo();
|
||||
}
|
||||
return RTGCtrl::Instance().UpdateAndGetLoad(tgid);
|
||||
}
|
||||
|
||||
RTGLoadInfo GetLoad(pid_t tid)
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return RTGLoadInfo();
|
||||
}
|
||||
return RTGCtrl::Instance().UpdateAndGetLoad(tgid, tid);
|
||||
}
|
||||
|
||||
bool SetWindowSize(uint64_t size)
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().SetGroupWindowSize(tgid, size);
|
||||
}
|
||||
|
||||
bool SetInvalidInterval(uint64_t invalidMs)
|
||||
{
|
||||
if (!Enabled()) {
|
||||
return false;
|
||||
}
|
||||
return RTGCtrl::Instance().SetInvalidInterval(tgid, invalidMs);
|
||||
}
|
||||
|
||||
static pid_t GetTID()
|
||||
{
|
||||
return RTGCtrl::GetTID();
|
||||
}
|
||||
|
||||
bool isBegin()
|
||||
{
|
||||
return isbegin;
|
||||
}
|
||||
private:
|
||||
int tgid = -1;
|
||||
bool isbegin = false;
|
||||
};
|
||||
}; // namespace ffrt
|
||||
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 GLOBAL_CONFIG_H
|
||||
#define GLOBAL_CONFIG_H
|
||||
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
#include "types.h"
|
||||
|
||||
namespace ffrt {
|
||||
constexpr int DEFAULT_MINCONCURRENCY = 4;
|
||||
constexpr int INTERACTIVE_MAXCONCURRENCY = USE_COROUTINE ? 8 : 40000;
|
||||
constexpr int DEFAULT_MAXCONCURRENCY = USE_COROUTINE ? 8 : 80000;
|
||||
constexpr int DEFAULT_HARDLIMIT = USE_COROUTINE ? 16 : 128;
|
||||
constexpr int QOS_WORKER_MAXNUM = (8 * 16);
|
||||
|
||||
class GlobalConfig {
|
||||
public:
|
||||
GlobalConfig(const GlobalConfig&) = delete;
|
||||
|
||||
GlobalConfig& operator=(const GlobalConfig&) = delete;
|
||||
|
||||
~GlobalConfig() {}
|
||||
|
||||
static inline GlobalConfig& Instance()
|
||||
{
|
||||
static GlobalConfig cfg;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
void setCpuWorkerNum(const QoS& qos, int num)
|
||||
{
|
||||
if ((num <= 0) || (num > DEFAULT_MAXCONCURRENCY)) {
|
||||
num = DEFAULT_MAXCONCURRENCY;
|
||||
}
|
||||
this->cpu_worker_num[qos()] = static_cast<size_t>(num);
|
||||
}
|
||||
|
||||
size_t getCpuWorkerNum(const QoS& qos)
|
||||
{
|
||||
return this->cpu_worker_num[qos()];
|
||||
}
|
||||
|
||||
private:
|
||||
GlobalConfig()
|
||||
{
|
||||
for (auto qos = QoS::Min(); qos < QoS::Max(); ++qos) {
|
||||
if (qos == static_cast<int>(qos_user_interactive)) {
|
||||
this->cpu_worker_num[qos] = INTERACTIVE_MAXCONCURRENCY;
|
||||
} else {
|
||||
this->cpu_worker_num[qos] = DEFAULT_MAXCONCURRENCY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t cpu_worker_num[QoS::MaxNum()];
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* GLOBAL_CONFIG_H */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 NONCOPYABLE_HPP
|
||||
#define NONCOPYABLE_HPP
|
||||
namespace ffrt {
|
||||
struct NonCopyable {
|
||||
protected:
|
||||
NonCopyable() = default;
|
||||
~NonCopyable() = default;
|
||||
NonCopyable(const NonCopyable&) = delete;
|
||||
NonCopyable& operator=(const NonCopyable&) = delete;
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 __OSAL_HPP__
|
||||
#define __OSAL_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define API_ATTRIBUTE(attr) __attribute__(attr)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
|
||||
static inline unsigned int GetPid(void)
|
||||
{
|
||||
return getpid();
|
||||
}
|
||||
static inline unsigned int GetTid(void)
|
||||
{
|
||||
return syscall(SYS_gettid);
|
||||
}
|
||||
static inline std::string GetEnv(const char* name)
|
||||
{
|
||||
char* val = std::getenv(name);
|
||||
if (val == nullptr) {
|
||||
return "";
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void GetProcessName(char* processName, int bufferLength)
|
||||
{
|
||||
int fd = open("/proc/self/cmdline", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
ssize_t ret = syscall(SYS_read, fd, processName, bufferLength - 1);
|
||||
if (ret != -1) {
|
||||
processName[ret] = 0;
|
||||
}
|
||||
|
||||
syscall(SYS_close, fd);
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_TYPES_HPP
|
||||
#define FFRT_TYPES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ffrt {
|
||||
#ifdef CLOSE_COROUTINE_MODE
|
||||
constexpr bool USE_COROUTINE = false;
|
||||
#else
|
||||
constexpr bool USE_COROUTINE = true;
|
||||
#endif
|
||||
enum DT {
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
U64,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
FP16,
|
||||
FP32,
|
||||
FP64,
|
||||
};
|
||||
|
||||
enum class DevType {
|
||||
CPU,
|
||||
DEVMAX,
|
||||
};
|
||||
|
||||
enum class TaskType {
|
||||
ROOT,
|
||||
DEFAULT,
|
||||
};
|
||||
|
||||
enum class DataStatus {
|
||||
IDLE, // 默认状态
|
||||
READY, // 当前版本被生产出来,标志着这个版本的所有消费者可以执行
|
||||
CONSUMED, // 同时也是RELEASE,当前版本的所有消费者已经执行完成,标志着下一个版本的生产者可以执行
|
||||
MERGED, // 嵌套场景下,标志一个子任务的version已经被父任务的version合并
|
||||
};
|
||||
|
||||
enum class NestType {
|
||||
DEFAULT, // 不存在嵌套关系
|
||||
PARENTOUT, // 同parent的输出嵌套
|
||||
PARENTIN, // 同parent的输入嵌套
|
||||
};
|
||||
|
||||
/* Note: do not change the order of the enum values.
|
||||
* If a new value is added, or the order changed
|
||||
* make sure to update `StatusToString` as well.
|
||||
*/
|
||||
enum class TaskStatus : uint8_t {
|
||||
PENDING, // 任务创建后的初始状态
|
||||
ENQUEUED, // 队列任务插入队列中 (串行/并发队列任务)
|
||||
DEQUEUED, // 队列任务从队列中取出 (串行/并发队列任务)
|
||||
SUBMITTED, // 任务存在数据依赖
|
||||
READY, // 任务没有依赖/依赖解除
|
||||
POPPED, // 任务从ReadyQueue中取出,等待执行
|
||||
EXECUTING, // 任务执行在worker线程
|
||||
THREAD_BLOCK, // 任务由于FFRT同步原语进入线程阻塞状态
|
||||
COROUTINE_BLOCK, // 任务由于FFRT同步原语进入协程阻塞状态
|
||||
FINISH, // 任务执行完成,可解除依赖
|
||||
WAIT_RELEASING, // 任务资源等待回收 (父子嵌套依赖时,父任务完成但子任务还未完成,可以进入此状态)
|
||||
CANCELED, // 任务未执行前被取消 (cancel/skip语义)
|
||||
};
|
||||
|
||||
enum class AliveStatus : uint8_t {
|
||||
UNITINITED,
|
||||
INITED,
|
||||
RELEASED,
|
||||
};
|
||||
|
||||
enum class BlockType : uint8_t {
|
||||
BLOCK_COROUTINE,
|
||||
BLOCK_THREAD
|
||||
};
|
||||
|
||||
enum class Dependence : uint8_t {
|
||||
DEPENDENCE_INIT,
|
||||
DATA_DEPENDENCE,
|
||||
CALL_DEPENDENCE,
|
||||
CONDITION_DEPENDENCE,
|
||||
};
|
||||
|
||||
enum class SpecTaskType {
|
||||
EXIT_TASK,
|
||||
SLEEP_TASK,
|
||||
SPEC_TASK_MAX,
|
||||
};
|
||||
|
||||
enum SkipStatus : uint8_t {
|
||||
SUBMITTED,
|
||||
EXECUTED,
|
||||
SKIPPED,
|
||||
};
|
||||
#ifndef _MSC_VER
|
||||
#define FFRT_LIKELY(x) (__builtin_expect(!!(x), 1))
|
||||
#define FFRT_UNLIKELY(x) (__builtin_expect(!!(x), 0))
|
||||
#else
|
||||
#define FFRT_LIKELY(x) (x)
|
||||
#define FFRT_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#define FORCE_INLINE
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_BASE_QUEUE_H
|
||||
#define FFRT_BASE_QUEUE_H
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include "c/queue.h"
|
||||
#include "cpp/condition_variable.h"
|
||||
#include "internal_inc/non_copyable.h"
|
||||
#include "queue_strategy.h"
|
||||
|
||||
namespace ffrt {
|
||||
class QueueTask;
|
||||
class Loop;
|
||||
|
||||
enum QueueAction {
|
||||
INACTIVE = -1, // queue is nullptr or serial queue is empty
|
||||
SUCC,
|
||||
FAILED,
|
||||
CONCURRENT, // concurrency less than max concurrency
|
||||
};
|
||||
|
||||
class BaseQueue : public NonCopyable {
|
||||
public:
|
||||
BaseQueue();
|
||||
virtual ~BaseQueue() = default;
|
||||
|
||||
virtual int Push(QueueTask* task) = 0;
|
||||
virtual QueueTask* Pull() = 0;
|
||||
virtual bool GetActiveStatus() = 0;
|
||||
virtual int GetQueueType() const = 0;
|
||||
virtual int Remove();
|
||||
virtual int Remove(const char* name);
|
||||
virtual int Remove(const QueueTask* task);
|
||||
virtual void Stop();
|
||||
virtual uint64_t GetDueTaskCount();
|
||||
|
||||
virtual bool IsOnLoop()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int WaitAll()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual inline uint64_t GetMapSize()
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
return whenMap_.size();
|
||||
}
|
||||
|
||||
inline uint32_t GetQueueId() const
|
||||
{
|
||||
return queueId_;
|
||||
}
|
||||
|
||||
inline bool DelayStatus()
|
||||
{
|
||||
return delayStatus_.load();
|
||||
}
|
||||
|
||||
virtual bool HasTask(const char* name);
|
||||
virtual std::vector<QueueTask*> GetHeadTask();
|
||||
ffrt::mutex mutex_;
|
||||
protected:
|
||||
inline uint64_t GetNow() const
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
void Stop(std::multimap<uint64_t, QueueTask*>& whenMap);
|
||||
int Remove(std::multimap<uint64_t, QueueTask*>& whenMap);
|
||||
int Remove(const QueueTask* task, std::multimap<uint64_t, QueueTask*>& whenMap);
|
||||
int Remove(const char* name, std::multimap<uint64_t, QueueTask*>& whenMap);
|
||||
bool HasTask(const char* name, std::multimap<uint64_t, QueueTask*> whenMap);
|
||||
uint64_t GetDueTaskCount(std::multimap<uint64_t, QueueTask*>& whenMap);
|
||||
|
||||
const uint32_t queueId_;
|
||||
std::atomic_bool delayStatus_ { false };
|
||||
bool isExit_ { false };
|
||||
std::atomic_bool isActiveState_ { false };
|
||||
std::multimap<uint64_t, QueueTask*> whenMap_;
|
||||
std::vector<QueueTask*> headTaskVec_;
|
||||
QueueStrategy<QueueTask>::DequeFunc dequeFunc_ { nullptr };
|
||||
|
||||
ffrt::condition_variable cond_;
|
||||
};
|
||||
|
||||
std::unique_ptr<BaseQueue> CreateQueue(int queueType, const ffrt_queue_attr_t* attr);
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // FFRT_BASE_QUEUE_H
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 QUEUE_ATTR_PRIVATE_H
|
||||
#define QUEUE_ATTR_PRIVATE_H
|
||||
#include <string>
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
class queue_attr_private {
|
||||
public:
|
||||
queue_attr_private()
|
||||
: qos_(qos_default)
|
||||
{
|
||||
}
|
||||
|
||||
explicit queue_attr_private(const queue_attr attr)
|
||||
: qos_(attr.qos()),
|
||||
threadMode_(attr.thread_mode())
|
||||
{
|
||||
}
|
||||
|
||||
int qos_;
|
||||
uint64_t timeout_ = 0;
|
||||
int maxConcurrency_ = 1;
|
||||
ffrt_function_header_t* timeoutCb_ = nullptr;
|
||||
bool threadMode_ = false;
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_QUEUE_HANDLER_H
|
||||
#define FFRT_QUEUE_HANDLER_H
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <shared_mutex>
|
||||
#include <unordered_map>
|
||||
#include "c/queue.h"
|
||||
#include "c/queue_ext.h"
|
||||
#include "cpp/task.h"
|
||||
#include "base_queue.h"
|
||||
#include "sched/execute_ctx.h"
|
||||
#include "traffic_record.h"
|
||||
#include "tm/task_base.h"
|
||||
|
||||
namespace ffrt {
|
||||
class QueueTask;
|
||||
class SerialQueue;
|
||||
class Loop;
|
||||
|
||||
class QueueHandler {
|
||||
public:
|
||||
QueueHandler(const char* name, const ffrt_queue_attr_t* attr, const int type = ffrt_queue_serial);
|
||||
~QueueHandler();
|
||||
|
||||
void Cancel();
|
||||
void CancelAndWait();
|
||||
int Cancel(const char* name);
|
||||
int Cancel(QueueTask* task);
|
||||
void Dispatch(QueueTask* inTask);
|
||||
void Submit(QueueTask* task);
|
||||
void TransferTask(QueueTask* task);
|
||||
void TransferInitTask();
|
||||
|
||||
std::string GetDfxInfo(int index) const;
|
||||
std::pair<std::vector<uint64_t>, uint64_t> EvaluateTaskTimeout(uint64_t timeoutThreshold, uint64_t timeoutUs,
|
||||
std::stringstream& ss);
|
||||
|
||||
bool SetLoop(Loop* loop);
|
||||
bool ClearLoop();
|
||||
|
||||
inline bool IsOnLoop() const
|
||||
{
|
||||
return queue_->IsOnLoop();
|
||||
}
|
||||
|
||||
QueueTask* PickUpTask();
|
||||
|
||||
inline bool IsValidForLoop()
|
||||
{
|
||||
return !isUsed_.load() && (queue_->GetQueueType() == ffrt_queue_concurrent
|
||||
|| queue_->GetQueueType() == ffrt_queue_eventhandler_interactive);
|
||||
}
|
||||
|
||||
inline std::string GetName()
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
inline uint32_t GetQueueId()
|
||||
{
|
||||
FFRT_COND_DO_ERR((queue_ == nullptr), return 0, "queue construct failed");
|
||||
return queue_->GetQueueId();
|
||||
}
|
||||
|
||||
inline uint32_t GetExecTaskId() const
|
||||
{
|
||||
return execTaskId_.load();
|
||||
}
|
||||
|
||||
inline bool HasTask(const char* name)
|
||||
{
|
||||
FFRT_COND_DO_ERR((queue_ == nullptr), return false, "[queueId=%u] constructed failed", GetQueueId());
|
||||
return queue_->HasTask(name);
|
||||
}
|
||||
|
||||
inline uint64_t GetTaskCnt()
|
||||
{
|
||||
FFRT_COND_DO_ERR((queue_ == nullptr), return false, "[queueId=%u] constructed failed", GetQueueId());
|
||||
return queue_->GetMapSize();
|
||||
}
|
||||
|
||||
inline int WaitAll()
|
||||
{
|
||||
FFRT_COND_DO_ERR((queue_ == nullptr), return -1, "[queueId=%u] constructed failed", GetQueueId());
|
||||
return queue_->WaitAll();
|
||||
}
|
||||
|
||||
inline uint64_t GetQueueDueCount()
|
||||
{
|
||||
FFRT_COND_DO_ERR((queue_ == nullptr), return 0, "[queueId=%u] constructed failed", GetQueueId());
|
||||
return queue_->GetDueTaskCount();
|
||||
}
|
||||
|
||||
inline bool CheckDelayStatus()
|
||||
{
|
||||
return queue_->DelayStatus();
|
||||
}
|
||||
|
||||
bool IsIdle();
|
||||
void SetEventHandler(void* eventHandler);
|
||||
void* GetEventHandler();
|
||||
|
||||
int Dump(const char* tag, char* buf, uint32_t len, bool historyInfo = true);
|
||||
int DumpSize(ffrt_inner_queue_priority_t priority);
|
||||
|
||||
inline const std::unique_ptr<BaseQueue>& GetQueue()
|
||||
{
|
||||
return queue_;
|
||||
}
|
||||
|
||||
inline int GetType()
|
||||
{
|
||||
return queue_->GetQueueType();
|
||||
}
|
||||
|
||||
inline bool GetMode()
|
||||
{
|
||||
return threadMode_;
|
||||
}
|
||||
|
||||
private:
|
||||
void Deliver();
|
||||
void SetTimeoutMonitor(QueueTask* task);
|
||||
void RemoveTimeoutMonitor(QueueTask* task);
|
||||
void RunTimeOutCallback(QueueTask* task);
|
||||
|
||||
void ReportTimeout(const std::vector<std::pair<uint64_t, std::string>>& timeoutTaskInfo);
|
||||
bool ControlTimeoutFreq(uint64_t timeoutCnt);
|
||||
void CheckSchedDeadline();
|
||||
bool CheckExecutingTask();
|
||||
void SendSchedTimer(TimePoint delay);
|
||||
void AddSchedDeadline(QueueTask* task);
|
||||
void RemoveSchedDeadline(QueueTask* task);
|
||||
void ReportTaskTimeout(uint64_t timeoutUs, std::stringstream& ss, int index);
|
||||
uint64_t CheckTimeSchedule(uint64_t time, uint64_t timeoutUs);
|
||||
|
||||
void SetCurTask(QueueTask* task);
|
||||
void UpdateCurTask(QueueTask* task);
|
||||
|
||||
// queue info
|
||||
std::string name_;
|
||||
int qos_ = qos_default;
|
||||
std::unique_ptr<BaseQueue> queue_ = nullptr;
|
||||
std::atomic_bool isUsed_ = false;
|
||||
std::atomic_uint64_t execTaskId_ = 0;
|
||||
int maxConcurrency_ = 1;
|
||||
std::vector<QueueTask*> curTaskVec_;
|
||||
uint64_t desWaitCnt_ = 0;
|
||||
|
||||
// for timeout watchdog
|
||||
uint64_t timeout_ = 0;
|
||||
std::vector<TimeoutTask> timeoutTaskVec_;
|
||||
std::atomic_int delayedCbCnt_ = {0};
|
||||
ffrt_function_header_t* timeoutCb_ = nullptr;
|
||||
TrafficRecord trafficRecord_;
|
||||
uint64_t trafficRecordInterval_ = DEFAULT_TRAFFIC_INTERVAL;
|
||||
|
||||
ffrt::mutex mutex_;
|
||||
bool initSchedTimer_ = false;
|
||||
WaitUntilEntry* we_ = nullptr;
|
||||
std::unordered_map<QueueTask*, uint64_t> schedDeadline_;
|
||||
std::atomic_int deliverCnt_ = {0};
|
||||
bool threadMode_ = false;
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // FFRT_QUEUE_HANDLER_H
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_QUEUE_MONITOR_H
|
||||
#define FFRT_QUEUE_MONITOR_H
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <shared_mutex>
|
||||
#include "util/slab.h"
|
||||
#include "sched/execute_ctx.h"
|
||||
#include "tm/queue_task.h"
|
||||
|
||||
namespace ffrt {
|
||||
class QueueHandler;
|
||||
class QueueMonitor {
|
||||
public:
|
||||
static QueueMonitor &GetInstance();
|
||||
void RegisterQueue(QueueHandler* queue);
|
||||
void DeregisterQueue(QueueHandler* queue);
|
||||
void UpdateQueueInfo();
|
||||
std::string DumpQueueTimeoutInfo();
|
||||
|
||||
private:
|
||||
QueueMonitor();
|
||||
~QueueMonitor();
|
||||
QueueMonitor(const QueueMonitor &) = delete;
|
||||
QueueMonitor(QueueMonitor &&) = delete;
|
||||
QueueMonitor &operator=(const QueueMonitor &) = delete;
|
||||
QueueMonitor &operator=(QueueMonitor &&) = delete;
|
||||
|
||||
void SetAlarm(uint64_t steadyUs);
|
||||
void ScheduleAlarm();
|
||||
void CheckTimeout(uint64_t& nextTaskStart);
|
||||
void ReportEventTimeout(uint64_t curGid, const std::stringstream& ss);
|
||||
void UpdateTimeoutUs();
|
||||
|
||||
WaitUntilEntry* we_ = nullptr;
|
||||
std::atomic<uint64_t> timeoutUs_ = 0;
|
||||
std::stringstream timeoutMSG_;
|
||||
std::shared_mutex infoMutex_;
|
||||
std::atomic_bool suspendAlarm_ = {true};
|
||||
std::vector<QueueHandler*> queuesInfo_;
|
||||
std::vector<std::pair<uint64_t, std::string>> taskTimeoutInfo_;
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // FFRT_QUEUE_MONITOR_H
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_QUEUE_STRATEGY_H
|
||||
#define FFRT_QUEUE_STRATEGY_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "c/type_def.h"
|
||||
#include "c/queue_ext.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
|
||||
namespace ffrt {
|
||||
template<typename T>
|
||||
class QueueStrategy {
|
||||
public:
|
||||
using DequeFunc = T*(*)(const uint32_t, const uint64_t, std::multimap<uint64_t, T*>*, void*);
|
||||
|
||||
static T* DequeBatch(const uint32_t queueId, const uint64_t now,
|
||||
std::multimap<uint64_t, T*>* whenMapIn, void* args)
|
||||
{
|
||||
(void)args;
|
||||
auto& whenMap = *whenMapIn;
|
||||
// dequeue due tasks in batch
|
||||
T* head = whenMap.begin()->second;
|
||||
whenMap.erase(whenMap.begin());
|
||||
head->Dequeue();
|
||||
|
||||
T* node = head;
|
||||
while (!whenMap.empty() && whenMap.begin()->first < now) {
|
||||
auto next = whenMap.begin()->second;
|
||||
if (next->GetQos() != head->GetQos()) {
|
||||
break;
|
||||
}
|
||||
node->SetNextTask(next);
|
||||
whenMap.erase(whenMap.begin());
|
||||
next->Dequeue();
|
||||
node = next;
|
||||
}
|
||||
FFRT_LOGD("dequeue [gid=%llu -> gid=%llu], %u other tasks in [queueId=%u] ",
|
||||
head->gid, node->gid, whenMap.size(), queueId);
|
||||
return head;
|
||||
}
|
||||
|
||||
static T* DequeSingleByPriority(const uint32_t queueId,
|
||||
const uint64_t now, std::multimap<uint64_t, T*>* whenMapVec, void* args)
|
||||
{
|
||||
(void)args;
|
||||
// dequeue next expired task by priority
|
||||
int iterIndex = ffrt_queue_priority_idle;
|
||||
auto iterTarget = whenMapVec[iterIndex].cbegin();
|
||||
for (int idx = ffrt_queue_priority_immediate; idx <= ffrt_queue_priority_idle; idx++) {
|
||||
const auto& currentMap = whenMapVec[idx];
|
||||
if (currentMap.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (whenMapVec[iterIndex].empty() || iterTarget->first > currentMap.cbegin()->first) {
|
||||
iterIndex = idx;
|
||||
iterTarget = currentMap.cbegin();
|
||||
}
|
||||
}
|
||||
|
||||
for (int idx = ffrt_queue_priority_immediate; idx <= ffrt_queue_priority_idle; idx++) {
|
||||
const auto& currentMap = whenMapVec[idx];
|
||||
if (!currentMap.empty() && currentMap.cbegin()->first < now) {
|
||||
iterTarget = currentMap.cbegin();
|
||||
iterIndex = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
T* head = iterTarget->second;
|
||||
whenMapVec[iterIndex].erase(iterTarget);
|
||||
head->Dequeue();
|
||||
|
||||
size_t mapCount = 0;
|
||||
for (int idx = ffrt_queue_priority_immediate; idx <= ffrt_queue_priority_idle; idx++) {
|
||||
auto& currentMap = whenMapVec[idx];
|
||||
mapCount += currentMap.size();
|
||||
}
|
||||
FFRT_LOGD("dequeue [gid=%llu], %u other tasks in [queueId=%u] ", head->gid, mapCount, queueId);
|
||||
return head;
|
||||
}
|
||||
|
||||
static T* DequeSingleAgainstStarvation(const uint32_t queueId,
|
||||
const uint64_t now, std::multimap<uint64_t, T*>* whenMapVec, void* args)
|
||||
{
|
||||
// dequeue in descending order of priority
|
||||
// a low-priority task is dequeued every time five high-priority tasks are dequeued
|
||||
constexpr int maxPullTaskCount = 5;
|
||||
std::vector<int>* pulledTaskCount = static_cast<std::vector<int>*>(args);
|
||||
|
||||
int iterIndex = ffrt_inner_queue_priority_idle;
|
||||
auto iterTarget = whenMapVec[iterIndex].cbegin();
|
||||
for (int idx = 0; idx < ffrt_inner_queue_priority_idle; idx++) {
|
||||
const auto& currentMap = whenMapVec[idx];
|
||||
if (currentMap.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (whenMapVec[iterIndex].empty() || iterTarget->first > currentMap.cbegin()->first) {
|
||||
iterIndex = idx;
|
||||
iterTarget = currentMap.cbegin();
|
||||
}
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < ffrt_inner_queue_priority_idle; idx++) {
|
||||
if ((*pulledTaskCount)[idx] >= maxPullTaskCount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& currentMap = whenMapVec[idx];
|
||||
if (!currentMap.empty() && currentMap.cbegin()->first < now) {
|
||||
iterTarget = currentMap.cbegin();
|
||||
iterIndex = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
T* head = iterTarget->second;
|
||||
(*pulledTaskCount)[iterIndex]++;
|
||||
|
||||
for (int idx = 0; idx < iterIndex; idx++) {
|
||||
(*pulledTaskCount)[idx] = 0;
|
||||
}
|
||||
whenMapVec[iterIndex].erase(iterTarget);
|
||||
head->Dequeue();
|
||||
|
||||
size_t mapCount = 0;
|
||||
for (int idx = 0; idx <= ffrt_inner_queue_priority_idle; idx++) {
|
||||
auto& currentMap = whenMapVec[idx];
|
||||
mapCount += currentMap.size();
|
||||
}
|
||||
FFRT_LOGD("dequeue [gid=%llu], prio %d, %u other tasks in [queueId=%u] ",
|
||||
head->gid, head->GetPriority(), mapCount, queueId);
|
||||
|
||||
return head;
|
||||
}
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // FFRT_QUEUE_STRATEGY_H
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_SERIAL_QUEUE_H
|
||||
#define FFRT_SERIAL_QUEUE_H
|
||||
|
||||
#include "base_queue.h"
|
||||
|
||||
namespace ffrt {
|
||||
class SerialQueue : public BaseQueue {
|
||||
public:
|
||||
SerialQueue();
|
||||
~SerialQueue() override;
|
||||
|
||||
int Push(QueueTask* task) override;
|
||||
QueueTask* Pull() override;
|
||||
|
||||
bool GetActiveStatus() override
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
return isActiveState_.load();
|
||||
}
|
||||
|
||||
int GetQueueType() const override
|
||||
{
|
||||
return ffrt_queue_serial;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t overloadThreshold_;
|
||||
};
|
||||
|
||||
std::unique_ptr<BaseQueue> CreateSerialQueue(const ffrt_queue_attr_t* attr);
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // FFRT_SERIAL_QUEUE_H
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 FFRT_QUEUE_TRAFFIC_RECORD_H
|
||||
#define FFRT_QUEUE_TRAFFIC_RECORD_H
|
||||
|
||||
#include <vector>
|
||||
#include "queue/serial_queue.h"
|
||||
|
||||
namespace ffrt {
|
||||
constexpr uint64_t DEFAULT_TRAFFIC_INTERVAL = 6000000;
|
||||
|
||||
class QueueHandler;
|
||||
class TrafficRecord {
|
||||
public:
|
||||
explicit TrafficRecord();
|
||||
void SetTimeInterval(const uint64_t timeInterval);
|
||||
void SubmitTraffic(QueueHandler* handler);
|
||||
void DoneTraffic();
|
||||
void DoneTraffic(uint32_t count);
|
||||
static std::string DumpTrafficInfo(bool withLock = true);
|
||||
|
||||
static std::vector<std::pair<uint64_t, std::string>> trafficRecordInfo;
|
||||
private:
|
||||
void CalculateTraffic(QueueHandler* handler, const uint64_t& time);
|
||||
void ReportOverload(std::stringstream& ss);
|
||||
void DetectCountThreshold();
|
||||
|
||||
uint64_t timeInterval_ = DEFAULT_TRAFFIC_INTERVAL;
|
||||
uint64_t lastCheckTime_ = 0;
|
||||
uint64_t lastReportTime_ = 0;
|
||||
std::atomic_uint32_t detectCnt_ = 0;
|
||||
std::atomic_uint64_t nextUpdateTime_ = 0;
|
||||
|
||||
std::atomic_uint32_t submitCnt_ = 0;
|
||||
std::atomic_uint32_t doneCnt_ = 0;
|
||||
|
||||
std::atomic_uint32_t doneCntOld_ = 0;
|
||||
std::atomic_uint32_t submitCntOld_ = 0;
|
||||
|
||||
static std::mutex mtx_;
|
||||
int recordIndex_ = 0;
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // FFRT_QUEUE_TRAFFIC_RECORD_H
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_EXECUTE_CTX_HPP
|
||||
#define FFRT_EXECUTE_CTX_HPP
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <atomic>
|
||||
|
||||
#include "util/linked_list.h"
|
||||
#include "c/executor_task.h"
|
||||
#include "util/spmc_queue.h"
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
using TimePoint = std::chrono::steady_clock::time_point;
|
||||
|
||||
enum class TaskTimeoutState {
|
||||
INIT,
|
||||
NOTIFIED,
|
||||
TIMEOUT,
|
||||
};
|
||||
|
||||
enum class SharedMutexWaitType {
|
||||
NORMAL,
|
||||
READ,
|
||||
WRITE,
|
||||
};
|
||||
|
||||
enum class we_status {
|
||||
INIT,
|
||||
NOTIFYING,
|
||||
TIMEOUT_DONE
|
||||
};
|
||||
|
||||
class TaskBase;
|
||||
class CoTask;
|
||||
|
||||
struct WaitEntry {
|
||||
WaitEntry() : prev(this), next(this), task(nullptr), wtType(SharedMutexWaitType::NORMAL) {
|
||||
}
|
||||
explicit WaitEntry(TaskBase *task) : prev(nullptr), next(nullptr), task(task),
|
||||
wtType(SharedMutexWaitType::NORMAL) {
|
||||
}
|
||||
LinkedList node;
|
||||
WaitEntry* prev;
|
||||
WaitEntry* next;
|
||||
TaskBase* task;
|
||||
SharedMutexWaitType wtType;
|
||||
};
|
||||
|
||||
struct WaitUntilEntry : WaitEntry {
|
||||
WaitUntilEntry() : WaitEntry(), status(we_status::INIT), hasWaitTime(false)
|
||||
{
|
||||
}
|
||||
explicit WaitUntilEntry(TaskBase* task) : WaitEntry(task), status(we_status::INIT), hasWaitTime(false)
|
||||
{
|
||||
}
|
||||
std::atomic<we_status> status;
|
||||
bool hasWaitTime;
|
||||
TimePoint tp;
|
||||
std::function<void(WaitEntry*)> cb;
|
||||
std::mutex wl;
|
||||
std::condition_variable cv;
|
||||
};
|
||||
// 当前Worker线程的状态信息
|
||||
struct ExecuteCtx {
|
||||
ExecuteCtx();
|
||||
virtual ~ExecuteCtx();
|
||||
|
||||
QoS qos;
|
||||
TaskBase* task; // 当前正在执行的Task
|
||||
WaitUntilEntry wn;
|
||||
uint64_t lastGid_ = 0;
|
||||
pid_t tid;
|
||||
|
||||
/**
|
||||
* @param init Should ExecuteCtx be initialized if it cannot be obtained
|
||||
*/
|
||||
static ExecuteCtx* Cur(bool init = true);
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_SCHEDULER_HPP
|
||||
#define FFRT_SCHEDULER_HPP
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <array>
|
||||
#include "core/entity.h"
|
||||
#include "eu/execute_unit.h"
|
||||
#include "sync/sync.h"
|
||||
#include "sched/task_scheduler.h"
|
||||
#include "tm/cpu_task.h"
|
||||
#include "util/cb_func.h"
|
||||
#include "dfx/bbox/bbox.h"
|
||||
|
||||
namespace ffrt {
|
||||
class Scheduler {
|
||||
public:
|
||||
Scheduler(const Scheduler&) = delete;
|
||||
Scheduler& operator=(const Scheduler&) = delete;
|
||||
virtual ~Scheduler()
|
||||
{
|
||||
tearDown = true;
|
||||
for (int i = 0; i < QoS::Max(); i++) {
|
||||
SchedulerFactory::Recycle(taskSchedulers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取调度器的单例
|
||||
static Scheduler* Instance();
|
||||
|
||||
inline TaskScheduler& GetScheduler(const QoS& qos)
|
||||
{
|
||||
return *taskSchedulers[static_cast<unsigned short>(qos)];
|
||||
}
|
||||
|
||||
void PushTask(const QoS& qos, TaskBase* task)
|
||||
{
|
||||
if (!tearDown && task) {
|
||||
taskSchedulers[qos]->PushTask(task);
|
||||
}
|
||||
}
|
||||
|
||||
TaskBase* PopTask(const QoS& qos)
|
||||
{
|
||||
if (tearDown) {
|
||||
return nullptr;
|
||||
}
|
||||
return taskSchedulers[qos]->PopTask();
|
||||
}
|
||||
|
||||
inline uint64_t GetTotalTaskCnt(const QoS& qos)
|
||||
{
|
||||
return taskSchedulers[static_cast<unsigned short>(qos)]->GetTotalTaskCnt();
|
||||
}
|
||||
|
||||
inline uint64_t GetGlobalTaskCnt(const QoS& qos)
|
||||
{
|
||||
return taskSchedulers[static_cast<unsigned short>(qos)]->GetGlobalTaskCnt();
|
||||
}
|
||||
|
||||
inline const TaskSchedMode& GetTaskSchedMode(const QoS& qos)
|
||||
{
|
||||
return taskSchedulers[static_cast<unsigned short>(qos)]->GetTaskSchedMode();
|
||||
}
|
||||
|
||||
bool CancelUVWork(ffrt_executor_task_t* uvWork, int qos);
|
||||
|
||||
inline SpmcQueue* GetWorkerLocalQueue(const QoS& qos, pid_t pid)
|
||||
{
|
||||
return taskSchedulers[static_cast<unsigned short>(qos)]->GetWorkerLocalQueue(pid);
|
||||
}
|
||||
|
||||
bool CheckUVTaskConcurrency(ffrt_executor_task_t* task, const QoS& qos);
|
||||
ffrt_executor_task_t* PickWaitingUVTask(const QoS& qos);
|
||||
|
||||
std::atomic_bool tearDown { false };
|
||||
|
||||
private:
|
||||
std::array<TaskScheduler*, QoS::MaxNum()> taskSchedulers;
|
||||
Scheduler()
|
||||
{
|
||||
for (int i = 0; i < QoS::Max(); i++) {
|
||||
taskSchedulers[i] = SchedulerFactory::Alloc();
|
||||
QoS qos = QoS(i);
|
||||
GetScheduler(i).SetQos(qos);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 FFRT_STASK_SCHEDULER_HPP
|
||||
#define FFRT_STASK_SCHEDULER_HPP
|
||||
#include "sched/task_scheduler.h"
|
||||
|
||||
namespace ffrt {
|
||||
class STaskScheduler : public TaskScheduler {
|
||||
public:
|
||||
STaskScheduler()
|
||||
{
|
||||
que = std::make_unique<FIFOQueue>();
|
||||
}
|
||||
|
||||
void SetQos(QoS &q) override
|
||||
{
|
||||
qos = q;
|
||||
}
|
||||
|
||||
uint64_t GetGlobalTaskCnt() override
|
||||
{
|
||||
return que->Size();
|
||||
}
|
||||
|
||||
private:
|
||||
bool PushTaskGlobal(TaskBase* task, bool rtb) override;
|
||||
TaskBase* PopTaskHybridProcess() override;
|
||||
|
||||
TaskBase* PopTaskGlobal() override
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(*GetMutex());
|
||||
TaskBase* task = que->DeQueue();
|
||||
lock.unlock();
|
||||
if (task && task->type == ffrt_uv_task) {
|
||||
return GetUVTask(task);
|
||||
}
|
||||
return task;
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<FIFOQueue> que { nullptr };
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_TASK_RUNQUEUE_HPP
|
||||
#define FFRT_TASK_RUNQUEUE_HPP
|
||||
|
||||
#include "tm/cpu_task.h"
|
||||
#include "tm/uv_task.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace ffrt {
|
||||
class FIFOQueue {
|
||||
public:
|
||||
void EnQueue(TaskBase* task)
|
||||
{
|
||||
list.PushBack(task->node);
|
||||
auto curSize = size.load(std::memory_order_relaxed);
|
||||
size.store(curSize + 1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void EnQueueBatch(TaskBase* first, TaskBase* last, size_t cnt)
|
||||
{
|
||||
list.PushBack(first->node, last->node);
|
||||
size += static_cast<int>(cnt);
|
||||
}
|
||||
|
||||
TaskBase* DeQueue()
|
||||
{
|
||||
if (list.Empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto node = list.PopFront();
|
||||
if (node == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TaskBase* task = node->ContainerOf(&TaskBase::node);
|
||||
auto curSize = size.load(std::memory_order_relaxed);
|
||||
assert(curSize > 0);
|
||||
size.store(curSize - 1, std::memory_order_relaxed);
|
||||
return task;
|
||||
}
|
||||
|
||||
bool Empty()
|
||||
{
|
||||
return list.Empty();
|
||||
}
|
||||
|
||||
int Size()
|
||||
{
|
||||
return size.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedList list;
|
||||
std::atomic<int> size = 0;
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 WORKGROUP_INCLUDE
|
||||
#define WORKGROUP_INCLUDE
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <cstdbool>
|
||||
#include <chrono>
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
|
||||
constexpr int RS_UID = 1003;
|
||||
constexpr int MAX_WG_THREADS = 32;
|
||||
#define MAX_FRAME_BUFFER 6
|
||||
#define gettid() syscall(SYS_gettid)
|
||||
namespace ffrt {
|
||||
enum WgType {
|
||||
TYPE_DEFAULT = 0,
|
||||
TYPE_RS = 1,
|
||||
TYPE_MAX
|
||||
};
|
||||
|
||||
struct WorkGroup {
|
||||
bool started;
|
||||
int rtgId;
|
||||
int tids[MAX_WG_THREADS];
|
||||
uint64_t interval;
|
||||
int qos;
|
||||
WgType type;
|
||||
};
|
||||
|
||||
#if (defined(QOS_FRAME_RTG))
|
||||
|
||||
struct WorkGroup* WorkgroupCreate(uint64_t interval, int qos);
|
||||
int WorkgroupClear(struct WorkGroup* wg);
|
||||
bool JoinWG(int tid, int qos);
|
||||
bool LeaveWG(int tid, int qos);
|
||||
|
||||
#else
|
||||
|
||||
#ifdef QOS_WORKER_FRAME_RTG
|
||||
WorkGroup* CreateRSWorkGroup(uint64_t interval, int qos);
|
||||
bool JoinRSWorkGroup(int tid, int qos);
|
||||
bool LeaveRSWorkGroup(int tid, int qos);
|
||||
bool DestoryRSWorkGroup(int qos);
|
||||
#endif
|
||||
|
||||
inline struct WorkGroup* WorkgroupCreate(uint64_t interval __attribute__((unused)), int qos)
|
||||
{
|
||||
#ifdef QOS_WORKER_FRAME_RTG
|
||||
int uid = getuid();
|
||||
if (uid == RS_UID) {
|
||||
return CreateRSWorkGroup(interval, qos);
|
||||
}
|
||||
#endif
|
||||
struct WorkGroup* wg = new (std::nothrow) struct WorkGroup();
|
||||
if (wg == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return wg;
|
||||
}
|
||||
|
||||
inline int WorkgroupClear(struct WorkGroup* wg)
|
||||
{
|
||||
#ifdef QOS_WORKER_FRAME_RTG
|
||||
int uid = getuid();
|
||||
if (uid == RS_UID) {
|
||||
return DestoryRSWorkGroup(wg->qos);
|
||||
}
|
||||
#endif
|
||||
delete wg;
|
||||
wg = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool JoinWG(int tid, int qos)
|
||||
{
|
||||
#ifdef QOS_WORKER_FRAME_RTG
|
||||
int uid = getuid();
|
||||
if (uid == RS_UID) {
|
||||
return JoinRSWorkGroup(tid, qos);
|
||||
}
|
||||
#endif
|
||||
(void)tid;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool LeaveWG(int tid, int qos)
|
||||
{
|
||||
#ifdef QOS_WORKER_FRAME_RTG
|
||||
int uid = getuid();
|
||||
if (uid == RS_UID) {
|
||||
return LeaveRSWorkGroup(tid, qos);
|
||||
}
|
||||
#endif
|
||||
(void)tid;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(QOS_FRAME_RTG)
|
||||
|
||||
void WorkgroupStartInterval(struct WorkGroup* wg);
|
||||
void WorkgroupStopInterval(struct WorkGroup* wg);
|
||||
void WorkgroupJoin(struct WorkGroup* wg, int tid);
|
||||
|
||||
#else /* !QOS_FRAME_RTG */
|
||||
|
||||
inline void WorkgroupStartInterval(struct WorkGroup* wg)
|
||||
{
|
||||
if (wg->started) {
|
||||
return;
|
||||
}
|
||||
wg->started = true;
|
||||
}
|
||||
|
||||
inline void WorkgroupStopInterval(struct WorkGroup* wg)
|
||||
{
|
||||
if (!wg->started) {
|
||||
return;
|
||||
}
|
||||
wg->started = false;
|
||||
}
|
||||
|
||||
inline void WorkgroupJoin(struct WorkGroup* wg, int tid)
|
||||
{
|
||||
(void)wg;
|
||||
(void)tid;
|
||||
}
|
||||
|
||||
#endif /* QOS_FRAME_RTG */
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 _DELAYED_WORKER_H_
|
||||
#define _DELAYED_WORKER_H_
|
||||
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include "cpp/sleep.h"
|
||||
#include "sched/execute_ctx.h"
|
||||
namespace ffrt {
|
||||
using TimePoint = std::chrono::steady_clock::time_point;
|
||||
|
||||
struct DelayedWork {
|
||||
WaitEntry* we;
|
||||
const std::function<void(WaitEntry*)>* cb;
|
||||
};
|
||||
|
||||
class DelayedWorker {
|
||||
std::multimap<TimePoint, DelayedWork> map;
|
||||
std::mutex lock;
|
||||
std::atomic_bool toExit = false;
|
||||
std::unique_ptr<std::thread> delayedWorker = nullptr;
|
||||
int noTaskDelayCount_{0};
|
||||
bool exited_ = true;
|
||||
int epollfd_{-1};
|
||||
int timerfd_{-1};
|
||||
#ifdef FFRT_WORKERS_DYNAMIC_SCALING
|
||||
int monitorfd_{-1};
|
||||
#endif
|
||||
std::atomic<int> asyncTaskCnt_ {0};
|
||||
int HandleWork(void);
|
||||
void ThreadInit();
|
||||
|
||||
public:
|
||||
static DelayedWorker &GetInstance();
|
||||
static void ThreadEnvCreate();
|
||||
static bool IsDelayerWorkerThread();
|
||||
|
||||
DelayedWorker(DelayedWorker const&) = delete;
|
||||
void operator=(DelayedWorker const&) = delete;
|
||||
|
||||
bool dispatch(const TimePoint& to, WaitEntry* we, const std::function<void(WaitEntry*)>& wakeup,
|
||||
bool skipTimeCheck = false);
|
||||
bool remove(const TimePoint& to, WaitEntry* we);
|
||||
void SubmitAsyncTask(std::function<void()>&& func);
|
||||
void Terminate();
|
||||
|
||||
private:
|
||||
DelayedWorker();
|
||||
void DumpMap();
|
||||
~DelayedWorker();
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 HICORO_POLLER_H
|
||||
#define HICORO_POLLER_H
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#endif
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
#include "sync/sync.h"
|
||||
#include "tm/task_base.h"
|
||||
#include "internal_inc/non_copyable.h"
|
||||
#include "c/executor_task.h"
|
||||
#include "c/timer.h"
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
#include "dfx/trace/ffrt_trace_chain.h"
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
enum class PollerRet {
|
||||
RET_NULL,
|
||||
RET_EPOLL,
|
||||
RET_TIMER,
|
||||
};
|
||||
|
||||
enum class EpollStatus {
|
||||
WAIT,
|
||||
WAKE,
|
||||
TEARDOWN,
|
||||
};
|
||||
|
||||
enum class TimerStatus {
|
||||
EXECUTING,
|
||||
EXECUTED,
|
||||
};
|
||||
|
||||
constexpr int EPOLL_EVENT_SIZE = 1024;
|
||||
|
||||
struct WakeDataWithCb {
|
||||
WakeDataWithCb() {}
|
||||
WakeDataWithCb(int fdVal, void *dataVal, std::function<void(void *, uint32_t)> cbVal, CoTask *taskVal)
|
||||
: fd(fdVal), data(dataVal), cb(cbVal), task(taskVal)
|
||||
{
|
||||
if (cb != nullptr) {
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
if (TraceChainAdapter::Instance().HiTraceChainGetId().valid == HITRACE_ID_VALID) {
|
||||
traceId = TraceChainAdapter::Instance().HiTraceChainCreateSpan();
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int fd = 0;
|
||||
void* data = nullptr;
|
||||
std::function<void(void*, uint32_t)> cb = nullptr;
|
||||
CoTask* task = nullptr;
|
||||
uint32_t monitorEvents = 0;
|
||||
HiTraceIdStruct traceId;
|
||||
};
|
||||
|
||||
struct TimerDataWithCb {
|
||||
TimerDataWithCb() {}
|
||||
TimerDataWithCb(void *dataVal, std::function<void(void *)> cbVal, CoTask *taskVal, bool repeat, uint64_t timeout)
|
||||
: data(dataVal), cb(cbVal), task(taskVal), repeat(repeat), timeout(timeout)
|
||||
{
|
||||
if (cb != nullptr) {
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
if (TraceChainAdapter::Instance().HiTraceChainGetId().valid == HITRACE_ID_VALID) {
|
||||
traceId = TraceChainAdapter::Instance().HiTraceChainCreateSpan();
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void* data = nullptr;
|
||||
std::function<void(void*)> cb = nullptr;
|
||||
int handle = -1;
|
||||
CoTask* task = nullptr;
|
||||
bool repeat = false;
|
||||
uint64_t timeout = 0;
|
||||
HiTraceIdStruct traceId;
|
||||
};
|
||||
|
||||
struct SyncData {
|
||||
SyncData() {}
|
||||
SyncData(void *eventsPtr, int maxEvents, int *nfdsPtr, TimePoint waitTP)
|
||||
: eventsPtr(eventsPtr), maxEvents(maxEvents), nfdsPtr(nfdsPtr), waitTP(waitTP)
|
||||
{}
|
||||
|
||||
void* eventsPtr = nullptr;
|
||||
int maxEvents = 0;
|
||||
int* nfdsPtr = nullptr;
|
||||
TimePoint waitTP;
|
||||
int timerHandle = -1;
|
||||
};
|
||||
|
||||
using EventVec = typename std::vector<epoll_event>;
|
||||
class Poller : private NonCopyable {
|
||||
using WakeDataList = typename std::list<std::unique_ptr<struct WakeDataWithCb>>;
|
||||
public:
|
||||
Poller() noexcept;
|
||||
~Poller() noexcept;
|
||||
|
||||
int AddFdEvent(int op, uint32_t events, int fd, void* data, ffrt_poller_cb cb) noexcept;
|
||||
int DelFdEvent(int fd) noexcept;
|
||||
int WaitFdEvent(struct epoll_event *eventsVec, int maxevents, int timeout) noexcept;
|
||||
|
||||
PollerRet PollOnce(int timeout = -1) noexcept;
|
||||
void WakeUp() noexcept;
|
||||
|
||||
int RegisterTimer(uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat = false) noexcept;
|
||||
int UnregisterTimer(int handle) noexcept;
|
||||
ffrt_timer_query_t GetTimerStatus(int handle) noexcept;
|
||||
|
||||
uint64_t GetPollCount() noexcept;
|
||||
|
||||
uint64_t GetTaskWaitTime(CoTask* task) noexcept;
|
||||
|
||||
bool DetermineEmptyMap() noexcept;
|
||||
bool DeterminePollerReady() noexcept;
|
||||
|
||||
void ClearCachedEvents(CoTask* task) noexcept;
|
||||
|
||||
private:
|
||||
void ReleaseFdWakeData() noexcept;
|
||||
void WakeSyncTask(std::unordered_map<CoTask*, EventVec>& syncTaskEvents) noexcept;
|
||||
void ProcessWaitedFds(int nfds, std::unordered_map<CoTask*, EventVec>& syncTaskEvents,
|
||||
std::array<epoll_event, EPOLL_EVENT_SIZE>& waitedEvents) noexcept;
|
||||
|
||||
void ExecuteTimerCb(TimePoint timer) noexcept;
|
||||
void ProcessTimerDataCb(CoTask* task) noexcept;
|
||||
void RegisterTimerImpl(const TimerDataWithCb& data) noexcept;
|
||||
|
||||
void CacheEventsAndDoMask(CoTask* task, EventVec& eventVec) noexcept;
|
||||
int FetchCachedEventAndDoUnmask(CoTask* task, struct epoll_event* eventsVec) noexcept;
|
||||
int FetchCachedEventAndDoUnmask(EventVec& cachedEventsVec, struct epoll_event* eventsVec) noexcept;
|
||||
|
||||
inline void CacheDelFd(int fd, CoTask *task) noexcept
|
||||
{
|
||||
m_delFdCacheMap.emplace(fd, task);
|
||||
}
|
||||
|
||||
inline void CacheMaskWakeData(CoTask* task, std::unique_ptr<struct WakeDataWithCb>& maskWakeData) noexcept
|
||||
{
|
||||
m_maskWakeDataWithCbMap[task].emplace_back(std::move(maskWakeData));
|
||||
}
|
||||
|
||||
void CacheMaskFdAndEpollDel(int fd, CoTask *task) noexcept;
|
||||
int ClearMaskWakeDataWithCbCache(CoTask *task) noexcept;
|
||||
int ClearMaskWakeDataWithCbCacheWithFd(CoTask *task, int fd) noexcept;
|
||||
int ClearDelFdCache(int fd) noexcept;
|
||||
|
||||
bool IsFdExist() noexcept;
|
||||
bool IsTimerReady() noexcept;
|
||||
|
||||
int m_epFd;
|
||||
std::atomic<uint64_t> pollerCount_ = 0;
|
||||
int timerHandle_ = -1;
|
||||
std::atomic<EpollStatus> flag_ = EpollStatus::WAKE;
|
||||
struct WakeDataWithCb m_wakeData;
|
||||
std::unordered_map<int, WakeDataList> m_wakeDataMap;
|
||||
std::unordered_map<int, int> m_delCntMap;
|
||||
std::unordered_map<CoTask*, SyncData> m_waitTaskMap;
|
||||
std::unordered_map<CoTask*, EventVec> m_cachedTaskEvents;
|
||||
|
||||
std::unordered_map<int, CoTask*> m_delFdCacheMap;
|
||||
std::unordered_map<CoTask*, WakeDataList> m_maskWakeDataWithCbMap;
|
||||
|
||||
std::unordered_map<int, TimerStatus> executedHandle_;
|
||||
std::multimap<TimePoint, TimerDataWithCb> timerMap_;
|
||||
std::atomic_bool fdEmpty_ {true};
|
||||
std::atomic_bool timerEmpty_ {true};
|
||||
mutable spin_mutex m_mapMutex;
|
||||
mutable spin_mutex timerMutex_;
|
||||
};
|
||||
|
||||
struct PollerProxy {
|
||||
public:
|
||||
static PollerProxy& Instance();
|
||||
|
||||
Poller& GetPoller(const QoS& qos = QoS(ffrt_qos_default))
|
||||
{
|
||||
return qosPollers[static_cast<size_t>(qos())];
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<Poller, QoS::MaxNum()> qosPollers;
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 UTIL_SYNC_HPP
|
||||
#define UTIL_SYNC_HPP
|
||||
// Provide synchronization primitives
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include "sched/execute_ctx.h"
|
||||
|
||||
namespace ffrt {
|
||||
namespace sync_detail {
|
||||
const int UNLOCK = 0;
|
||||
const int LOCK = 1;
|
||||
const int WAIT = 2;
|
||||
} // namespace sync_detail
|
||||
|
||||
class spin_mutex {
|
||||
std::atomic<int> l;
|
||||
void lock_contended();
|
||||
|
||||
public:
|
||||
spin_mutex() : l(sync_detail::UNLOCK)
|
||||
{
|
||||
}
|
||||
spin_mutex(spin_mutex const&) = delete;
|
||||
void operator=(spin_mutex const&) = delete;
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (l.exchange(sync_detail::LOCK, std::memory_order_acquire) == sync_detail::UNLOCK) {
|
||||
return;
|
||||
}
|
||||
lock_contended();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
l.store(sync_detail::UNLOCK, std::memory_order_release);
|
||||
}
|
||||
};
|
||||
|
||||
class fast_mutex {
|
||||
int l;
|
||||
void lock_contended();
|
||||
|
||||
public:
|
||||
fast_mutex() : l(sync_detail::UNLOCK)
|
||||
{
|
||||
}
|
||||
fast_mutex(fast_mutex const&) = delete;
|
||||
void operator=(fast_mutex const&) = delete;
|
||||
|
||||
void lock()
|
||||
{
|
||||
int v = sync_detail::UNLOCK;
|
||||
if (__atomic_compare_exchange_n(&l, &v, sync_detail::LOCK, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
|
||||
return;
|
||||
}
|
||||
lock_contended();
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int v = sync_detail::UNLOCK;
|
||||
return __atomic_compare_exchange_n(&l, &v, sync_detail::LOCK, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if (__atomic_exchange_n(&l, sync_detail::UNLOCK, __ATOMIC_RELEASE) == sync_detail::WAIT) {
|
||||
syscall(SYS_futex, &l, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool DelayedWakeup(const TimePoint& to, WaitEntry* we, const std::function<void(WaitEntry*)>& wakeup,
|
||||
bool skipTimeCheck = false);
|
||||
bool DelayedRemove(const TimePoint& to, WaitEntry* we);
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 FFRT_TIMER_MANAGER_HPP
|
||||
#define FFRT_TIMER_MANAGER_HPP
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include "internal_inc/osal.h"
|
||||
#include "internal_inc/non_copyable.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
#include "cpp/queue.h"
|
||||
#include "sync/sync.h"
|
||||
#include "sched/execute_ctx.h"
|
||||
#include "tm/task_base.h"
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
#include "dfx/trace/ffrt_trace_chain.h"
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
/** un-repeat timer: not_executed -> executintg -> executed -> ereased **/
|
||||
/** repeat timer: not_executed -> executintg -> executed -> executing -> executed ... **/
|
||||
enum class TimerState {
|
||||
NOT_EXECUTED, // the timer has not expired (in the initialization state).
|
||||
EXECUTING, // The timer has expired and is executing the callback.
|
||||
EXECUTED, // The timer has expired and the callback has been executed completely.
|
||||
INVALID
|
||||
};
|
||||
|
||||
struct TimerData {
|
||||
TimerData(void *dataVal, std::function<void(void *)> cbVal, bool repeat, int qos, uint64_t timeout)
|
||||
: data(dataVal), cb(cbVal), repeat(repeat), qos(qos), timeout(timeout)
|
||||
{
|
||||
if (cb != nullptr) {
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
if (TraceChainAdapter::Instance().HiTraceChainGetId().valid == HITRACE_ID_VALID) {
|
||||
traceId = TraceChainAdapter::Instance().HiTraceChainCreateSpan();
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void* data;
|
||||
std::function<void(void*)> cb;
|
||||
bool repeat;
|
||||
int qos;
|
||||
uint64_t timeout;
|
||||
int handle;
|
||||
TimerState state {TimerState::NOT_EXECUTED};
|
||||
HiTraceIdStruct traceId;
|
||||
};
|
||||
|
||||
class TimerManager : private NonCopyable {
|
||||
public:
|
||||
~TimerManager();
|
||||
static TimerManager& Instance();
|
||||
|
||||
ffrt_timer_t RegisterTimer(int qos, uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat = false) noexcept;
|
||||
int UnregisterTimer(ffrt_timer_t handle) noexcept;
|
||||
ffrt_timer_query_t GetTimerStatus(ffrt_timer_t handle) noexcept;
|
||||
|
||||
private:
|
||||
TimerManager();
|
||||
|
||||
void InitWorkQueAndCb(int qos);
|
||||
void RegisterTimerImpl(std::shared_ptr<TimerData> data);
|
||||
|
||||
mutable spin_mutex timerMutex_;
|
||||
ffrt_timer_t timerHandle_ { -1 };
|
||||
bool teardown { false };
|
||||
std::unordered_map<int, std::shared_ptr<TimerData>> timerMap_; // valid timer data manage
|
||||
std::array<uint64_t, QoS::MaxNum()> workQueDeps; // deps to ensure callbacks execute in order
|
||||
std::array<std::function<void(WaitEntry*)>, QoS::MaxNum()> workCb; // timeout cb for submit timer cb to queue
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 _CPU_TASK_H_
|
||||
#define _CPU_TASK_H_
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unistd.h>
|
||||
#include "task_base.h"
|
||||
#include "eu/co_routine.h"
|
||||
#include "core/task_attr_private.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
#include "eu/func_manager.h"
|
||||
#ifdef FFRT_ASYNC_STACKTRACE
|
||||
#include "dfx/async_stack/ffrt_async_stack.h"
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
constexpr int CO_CREATE_RETRY_INTERVAL = 500 * 1000;
|
||||
constexpr uint64_t MASK_FOR_HCS_TASK = 0xFF000000000000;
|
||||
struct VersionCtx;
|
||||
class SCPUEUTask;
|
||||
|
||||
#ifdef FFRT_TASK_LOCAL_ENABLE
|
||||
struct TaskLocalAttr {
|
||||
bool taskLocal = false; // 是否开启taskLocal特性
|
||||
void** threadTsd = nullptr; // 指向保存线程tsd数据内存空间的指针
|
||||
void** tsd = nullptr; // 指向task自身tsd数据内存空间的指针
|
||||
};
|
||||
#endif
|
||||
|
||||
class CPUEUTask : public CoTask {
|
||||
public:
|
||||
CPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id);
|
||||
~CPUEUTask() override;
|
||||
SkipStatus skipped = SkipStatus::SUBMITTED;
|
||||
|
||||
CPUEUTask* parent = nullptr;
|
||||
uint64_t delayTime = 0;
|
||||
TimeoutTask timeoutTask;
|
||||
|
||||
std::vector<CPUEUTask*>* in_handles_ = nullptr;
|
||||
/* The current number of child nodes does not represent the real number of child nodes,
|
||||
* because the dynamic graph child nodes will grow to assist in the generation of id
|
||||
*/
|
||||
std::atomic<uint64_t> childNum {0};
|
||||
bool isWatchdogEnable = false;
|
||||
bool notifyWorker_ = true;
|
||||
bool isDelaying = false;
|
||||
|
||||
#ifdef FFRT_TASK_LOCAL_ENABLE
|
||||
TaskLocalAttr* tlsAttr = nullptr;
|
||||
#endif
|
||||
|
||||
inline bool IsRoot() const
|
||||
{
|
||||
return parent == nullptr;
|
||||
}
|
||||
|
||||
inline void SetInHandles(std::vector<CPUEUTask*>& in_handles)
|
||||
{
|
||||
if (in_handles.empty()) {
|
||||
return;
|
||||
}
|
||||
in_handles_ = new std::vector<CPUEUTask*>(in_handles);
|
||||
}
|
||||
|
||||
inline const std::vector<CPUEUTask*>& GetInHandles()
|
||||
{
|
||||
static const std::vector<CPUEUTask*> empty;
|
||||
if (!in_handles_) {
|
||||
return empty;
|
||||
}
|
||||
return *in_handles_;
|
||||
}
|
||||
|
||||
void Prepare() override;
|
||||
void Ready() override;
|
||||
|
||||
void Pop() override
|
||||
{
|
||||
SetStatus(TaskStatus::POPPED);
|
||||
}
|
||||
|
||||
void Execute() override;
|
||||
|
||||
BlockType Block() override
|
||||
{
|
||||
if (USE_COROUTINE && !IsRoot() && legacyCountNum <= 0) {
|
||||
blockType = BlockType::BLOCK_COROUTINE;
|
||||
SetStatus(TaskStatus::COROUTINE_BLOCK);
|
||||
} else {
|
||||
blockType = BlockType::BLOCK_THREAD;
|
||||
SetStatus(TaskStatus::THREAD_BLOCK);
|
||||
}
|
||||
return blockType;
|
||||
}
|
||||
|
||||
void Wake() override
|
||||
{
|
||||
SetStatus(TaskStatus::EXECUTING);
|
||||
blockType = BlockType::BLOCK_COROUTINE;
|
||||
}
|
||||
|
||||
void Cancel() override
|
||||
{
|
||||
SetStatus(TaskStatus::CANCELED);
|
||||
}
|
||||
|
||||
void FreeMem() override;
|
||||
void SetQos(const QoS& newQos) override;
|
||||
|
||||
BlockType GetBlockType() const override
|
||||
{
|
||||
if (IsRoot()) {
|
||||
return BlockType::BLOCK_THREAD;
|
||||
}
|
||||
return blockType;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool NeedNotifyWorker(TaskBase* task)
|
||||
{
|
||||
if (task == nullptr) {
|
||||
return false;
|
||||
}
|
||||
bool needNotify = true;
|
||||
if (task->type == ffrt_normal_task) {
|
||||
CPUEUTask* cpuTask = static_cast<CPUEUTask*>(task);
|
||||
needNotify = cpuTask->notifyWorker_;
|
||||
cpuTask->notifyWorker_ = true;
|
||||
}
|
||||
return needNotify;
|
||||
}
|
||||
|
||||
inline bool isDelayingTask(CPUEUTask* task)
|
||||
{
|
||||
return task->isDelaying;
|
||||
}
|
||||
} /* namespace ffrt */
|
||||
#endif
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 _IO_TASK_H_
|
||||
#define _IO_TASK_H_
|
||||
|
||||
#include "task_base.h"
|
||||
#include "core/task_io.h"
|
||||
#include "core/task_attr_private.h"
|
||||
#include "tm/task_factory.h"
|
||||
#include "util/ffrt_facade.h"
|
||||
|
||||
namespace ffrt {
|
||||
class IOTask : public TaskBase {
|
||||
public:
|
||||
IOTask(const ffrt_io_callable_t& work, const task_attr_private* attr);
|
||||
|
||||
void Prepare() override {}
|
||||
|
||||
void Ready() override
|
||||
{
|
||||
QoS taskQos = qos_;
|
||||
FFRTTraceRecord::TaskSubmit<ffrt_io_task>(taskQos);
|
||||
SetStatus(TaskStatus::READY);
|
||||
FFRTFacade::GetSchedInstance()->GetScheduler(taskQos).PushTaskGlobal(this);
|
||||
FFRTTraceRecord::TaskEnqueue<ffrt_io_task>(taskQos);
|
||||
FFRTFacade::GetEUInstance().NotifyTask<TaskNotifyType::TASK_LOCAL>(taskQos);
|
||||
}
|
||||
|
||||
void Pop() override
|
||||
{
|
||||
SetStatus(TaskStatus::POPPED);
|
||||
}
|
||||
|
||||
void Execute() override;
|
||||
|
||||
BlockType Block() override
|
||||
{
|
||||
SetStatus(TaskStatus::THREAD_BLOCK);
|
||||
return BlockType::BLOCK_THREAD;
|
||||
}
|
||||
|
||||
void Wake() override
|
||||
{
|
||||
SetStatus(TaskStatus::EXECUTING);
|
||||
}
|
||||
|
||||
void Finish() override {}
|
||||
void Cancel() override {}
|
||||
|
||||
void FreeMem() override
|
||||
{
|
||||
TaskFactory<IOTask>::Free(this);
|
||||
}
|
||||
|
||||
void SetQos(const QoS& newQos) override
|
||||
{
|
||||
qos_ = newQos;
|
||||
}
|
||||
|
||||
std::string GetLabel() const override
|
||||
{
|
||||
return "io-task";
|
||||
}
|
||||
|
||||
BlockType GetBlockType() const override
|
||||
{
|
||||
return BlockType::BLOCK_THREAD;
|
||||
}
|
||||
|
||||
private:
|
||||
ffrt_io_callable_t work;
|
||||
};
|
||||
} /* namespace ffrt */
|
||||
#endif
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_QUEUE_TASK_H
|
||||
#define FFRT_QUEUE_TASK_H
|
||||
|
||||
#include <atomic>
|
||||
#include <regex>
|
||||
#include "queue/queue_attr_private.h"
|
||||
#include "queue/queue_handler.h"
|
||||
#include "tm/task_factory.h"
|
||||
#ifdef FFRT_ENABLE_HITRACE_CHAIN
|
||||
#include "dfx/trace/ffrt_trace_chain.h"
|
||||
#endif
|
||||
|
||||
#define GetQueueTaskByFuncStorageOffset(f) \
|
||||
(reinterpret_cast<QueueTask*>(static_cast<uintptr_t>(static_cast<size_t>(reinterpret_cast<uintptr_t>(f)) - \
|
||||
(reinterpret_cast<size_t>(&((reinterpret_cast<QueueTask*>(0))->func_storage))))))
|
||||
|
||||
namespace ffrt {
|
||||
class QueueTask : public CoTask {
|
||||
public:
|
||||
explicit QueueTask(QueueHandler* handler, const task_attr_private* attr = nullptr, bool insertHead = false);
|
||||
~QueueTask() override;
|
||||
|
||||
void Wait();
|
||||
void Notify();
|
||||
void Destroy();
|
||||
|
||||
uint32_t GetQueueId() const;
|
||||
|
||||
inline uint64_t GetDelay() const
|
||||
{
|
||||
return delay_;
|
||||
}
|
||||
|
||||
inline uint64_t GetUptime() const
|
||||
{
|
||||
return uptime_;
|
||||
}
|
||||
|
||||
inline QueueHandler* GetHandler() const
|
||||
{
|
||||
return handler_;
|
||||
}
|
||||
|
||||
inline bool GetFinishStatus() const
|
||||
{
|
||||
return isFinished_.load();
|
||||
}
|
||||
|
||||
inline QueueTask* GetNextTask() const
|
||||
{
|
||||
return nextTask_;
|
||||
}
|
||||
|
||||
inline void SetNextTask(QueueTask* task)
|
||||
{
|
||||
nextTask_ = task;
|
||||
}
|
||||
|
||||
inline void SetPriority(const ffrt_queue_priority_t prio)
|
||||
{
|
||||
prio_ = prio;
|
||||
}
|
||||
|
||||
inline ffrt_queue_priority_t GetPriority()
|
||||
{
|
||||
return prio_;
|
||||
}
|
||||
|
||||
inline bool IsMatch(std::string name) const
|
||||
{
|
||||
std::string pattern = ".*_" + name + "_.*";
|
||||
return std::regex_match(label, std::regex(pattern));
|
||||
}
|
||||
|
||||
inline bool InsertHead() const
|
||||
{
|
||||
return insertHead_;
|
||||
}
|
||||
|
||||
inline uint64_t GetSchedTimeout() const
|
||||
{
|
||||
return schedTimeout_;
|
||||
}
|
||||
|
||||
inline void SetMonitorTask(WaitUntilEntry* monitorWe)
|
||||
{
|
||||
monitorWe_ = monitorWe;
|
||||
}
|
||||
|
||||
inline WaitUntilEntry* GetMonitorTask()
|
||||
{
|
||||
return monitorWe_;
|
||||
}
|
||||
|
||||
inline void MonitorTaskStart()
|
||||
{
|
||||
isWeStart_.store(true);
|
||||
}
|
||||
|
||||
inline bool IsMonitorTaskStart()
|
||||
{
|
||||
return isWeStart_;
|
||||
}
|
||||
int curTaskIdx = 0;
|
||||
|
||||
void Prepare() override;
|
||||
void Ready() override;
|
||||
|
||||
// dequeue means task has been pulled out from it's queue
|
||||
inline void Dequeue()
|
||||
{
|
||||
SetStatus(TaskStatus::DEQUEUED);
|
||||
}
|
||||
|
||||
// pop means task has been popped from scheduler
|
||||
void Pop() override
|
||||
{
|
||||
SetStatus(TaskStatus::POPPED);
|
||||
}
|
||||
|
||||
void Execute() override;
|
||||
|
||||
BlockType Block() override
|
||||
{
|
||||
if (USE_COROUTINE && !threadMode_ && legacyCountNum <= 0 && (handler_ && !handler_->IsOnLoop())) {
|
||||
blockType = BlockType::BLOCK_COROUTINE;
|
||||
SetStatus(TaskStatus::COROUTINE_BLOCK);
|
||||
} else {
|
||||
blockType = BlockType::BLOCK_THREAD;
|
||||
SetStatus(TaskStatus::THREAD_BLOCK);
|
||||
}
|
||||
return blockType;
|
||||
}
|
||||
|
||||
void Wake() override
|
||||
{
|
||||
SetStatus(TaskStatus::EXECUTING);
|
||||
blockType = BlockType::BLOCK_COROUTINE;
|
||||
}
|
||||
|
||||
void Finish() override;
|
||||
|
||||
void Cancel() override
|
||||
{
|
||||
FFRT_LOGD("cancel task[%llu] %s succ", gid, label.c_str());
|
||||
SetStatus(TaskStatus::CANCELED);
|
||||
Notify();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void FreeMem() override;
|
||||
|
||||
void SetQos(const QoS& newQos) override
|
||||
{
|
||||
qos_ = newQos;
|
||||
}
|
||||
|
||||
BlockType GetBlockType() const override
|
||||
{
|
||||
return blockType;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t uptime_;
|
||||
QueueHandler* handler_;
|
||||
bool insertHead_ = false;
|
||||
uint64_t delay_ = 0;
|
||||
uint64_t schedTimeout_ = 0;
|
||||
|
||||
QueueTask* nextTask_ = nullptr;
|
||||
std::atomic_bool isFinished_ = {false};
|
||||
bool onWait_ = {false};
|
||||
std::atomic_bool isWeStart_ = {false};
|
||||
|
||||
ffrt_queue_priority_t prio_ = ffrt_queue_priority_low;
|
||||
WaitUntilEntry* monitorWe_ = nullptr;
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif // FFRT_QUEUE_TASK_H
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 _SCPU_TASK_H_
|
||||
#define _SCPU_TASK_H_
|
||||
|
||||
#include "tm/cpu_task.h"
|
||||
|
||||
namespace ffrt {
|
||||
class SCPUEUTask : public CPUEUTask {
|
||||
public:
|
||||
SCPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id);
|
||||
std::unordered_set<VersionCtx*> ins;
|
||||
std::unordered_set<VersionCtx*> outs;
|
||||
|
||||
Dependence dependenceStatus {Dependence::DEPENDENCE_INIT};
|
||||
|
||||
union {
|
||||
std::atomic_uint64_t submitDep; // dependency refcnt during task submit
|
||||
std::atomic_uint64_t waitDep; // dependency refcnt during task execute when wait api called
|
||||
} dataRefCnt {0};
|
||||
std::atomic_uint64_t childRefCnt {0}; // unfinished children refcnt
|
||||
|
||||
inline void IncDepRef()
|
||||
{
|
||||
++dataRefCnt.submitDep;
|
||||
}
|
||||
void DecDepRef();
|
||||
|
||||
inline void IncChildRef()
|
||||
{
|
||||
++(static_cast<SCPUEUTask*>(parent)->childRefCnt);
|
||||
}
|
||||
void DecChildRef();
|
||||
|
||||
inline void IncWaitDataRef()
|
||||
{
|
||||
++dataRefCnt.waitDep;
|
||||
}
|
||||
void DecWaitDataRef();
|
||||
void MultiDependenceAdd(Dependence depType);
|
||||
|
||||
public:
|
||||
void Finish() override;
|
||||
};
|
||||
|
||||
class RootTask : public SCPUEUTask {
|
||||
public:
|
||||
RootTask(const task_attr_private* attr, SCPUEUTask* parent, const uint64_t& id) : SCPUEUTask(attr, parent, id)
|
||||
{
|
||||
}
|
||||
public:
|
||||
bool thread_exit = false;
|
||||
};
|
||||
|
||||
class RootTaskCtxWrapper {
|
||||
public:
|
||||
RootTaskCtxWrapper()
|
||||
{
|
||||
task_attr_private task_attr;
|
||||
root = new RootTask{&task_attr, nullptr, 0};
|
||||
}
|
||||
~RootTaskCtxWrapper()
|
||||
{
|
||||
std::unique_lock<decltype(root->mutex_)> lck(root->mutex_);
|
||||
if (root->childRefCnt == 0) {
|
||||
lck.unlock();
|
||||
delete root;
|
||||
} else {
|
||||
root->thread_exit = true;
|
||||
}
|
||||
}
|
||||
CPUEUTask* Root()
|
||||
{
|
||||
return root;
|
||||
}
|
||||
private:
|
||||
RootTask *root = nullptr;
|
||||
};
|
||||
} /* namespace ffrt */
|
||||
#endif
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 _TASK_BASE_H_
|
||||
#define _TASK_BASE_H_
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include "eu/co_routine.h"
|
||||
#include "internal_inc/types.h"
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
#include "sched/execute_ctx.h"
|
||||
#include "internal_inc/non_copyable.h"
|
||||
#include "util/time_format.h"
|
||||
#include "internal_inc/types.h"
|
||||
#include "core/task_attr_private.h"
|
||||
|
||||
namespace ffrt {
|
||||
static constexpr uint64_t cacheline_size = 64;
|
||||
|
||||
typedef struct HiTraceIdStruct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
uint64_t chainId : 60;
|
||||
uint64_t ver : 3;
|
||||
uint64_t valid : 1;
|
||||
|
||||
uint64_t parentSpanId : 26;
|
||||
uint64_t spanId : 26;
|
||||
uint64_t flags : 12;
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
uint64_t valid : 1;
|
||||
uint64_t ver : 3;
|
||||
uint64_t chainId : 60;
|
||||
|
||||
uint64_t flags : 12;
|
||||
uint64_t spanId : 26;
|
||||
uint64_t parentSpanId : 26;
|
||||
#else
|
||||
#error "ERROR: No BIG_LITTLE_ENDIAN defines."
|
||||
#endif
|
||||
} HiTraceIdStruct;
|
||||
constexpr uint64_t HITRACE_ID_VALID = 1;
|
||||
|
||||
struct TimeoutTask {
|
||||
uint64_t taskGid{0};
|
||||
uint64_t timeoutCnt{0};
|
||||
TaskStatus taskStatus{TaskStatus::PENDING};
|
||||
TimeoutTask() = default;
|
||||
TimeoutTask(uint64_t gid, uint64_t timeoutcnt, TaskStatus status)
|
||||
: taskGid(gid), timeoutCnt(timeoutcnt), taskStatus(status) {}
|
||||
};
|
||||
|
||||
class TaskBase : private NonCopyable {
|
||||
public:
|
||||
TaskBase(ffrt_executor_task_type_t type, const task_attr_private *attr);
|
||||
virtual ~TaskBase() = default;
|
||||
|
||||
// lifecycle actions
|
||||
virtual void Prepare() = 0;
|
||||
virtual void Ready() = 0;
|
||||
virtual void Pop() = 0;
|
||||
// must be called by a sync primitive when blocking this task.
|
||||
// return value indicates this task need to be blocked on thread or yield from it's coroutine.
|
||||
virtual BlockType Block() = 0;
|
||||
virtual void Wake() = 0;
|
||||
virtual void Execute() = 0;
|
||||
virtual void Finish() = 0;
|
||||
virtual void Cancel() = 0;
|
||||
virtual void FreeMem() = 0;
|
||||
|
||||
// must be called by a sync primitive when it wakes a blocking task.
|
||||
// return value indicates this task has been blocked whether on thread or yield from it's coroutine.
|
||||
virtual BlockType GetBlockType() const = 0;
|
||||
|
||||
// getters and setters
|
||||
virtual std::string GetLabel() const = 0;
|
||||
virtual void SetQos(const QoS& newQos) = 0;
|
||||
|
||||
inline int GetQos() const
|
||||
{
|
||||
return qos_();
|
||||
}
|
||||
|
||||
inline void SetStatus(TaskStatus statusIn)
|
||||
{
|
||||
/* Note this function can be called concurrently.
|
||||
* The following accesses can be interleaved.
|
||||
* We use atomic relaxed accesses in order to
|
||||
* combat data-races without incurring performance
|
||||
* overhead. Currently statusTime & preStatus
|
||||
* are only used in printing debug information
|
||||
* and don't play a role in the logic.
|
||||
*/
|
||||
statusTime.store(TimeStampCntvct(), std::memory_order_relaxed);
|
||||
preStatus.store(curStatus, std::memory_order_relaxed);
|
||||
curStatus.store(statusIn, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// delete ref setter functions, for memory management
|
||||
inline uint32_t IncDeleteRef()
|
||||
{
|
||||
auto v = rc.fetch_add(1);
|
||||
return v;
|
||||
}
|
||||
|
||||
inline uint32_t DecDeleteRef()
|
||||
{
|
||||
auto v = rc.fetch_sub(1);
|
||||
if (v == 1) {
|
||||
FreeMem();
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// returns the current g_taskId value
|
||||
static uint32_t GetLastGid();
|
||||
|
||||
// properties
|
||||
LinkedList node; // used on fifo fast que
|
||||
ffrt_executor_task_type_t type;
|
||||
const uint64_t gid; // global unique id in this process
|
||||
QoS qos_ = qos_default;
|
||||
std::atomic_uint32_t rc = 1; // reference count for delete
|
||||
std::atomic<TaskStatus> preStatus = TaskStatus::PENDING;
|
||||
std::atomic<TaskStatus> curStatus = TaskStatus::PENDING;
|
||||
std::atomic<uint64_t> statusTime = TimeStampCntvct();
|
||||
std::atomic<AliveStatus> aliveStatus {AliveStatus::UNITINITED};
|
||||
|
||||
#ifdef FFRT_ASYNC_STACKTRACE
|
||||
uint64_t stackId = 0;
|
||||
#endif
|
||||
|
||||
struct HiTraceIdStruct traceId_ = {};
|
||||
uint64_t createTime {0};
|
||||
uint64_t executeTime {0};
|
||||
int32_t fromTid {0};
|
||||
};
|
||||
|
||||
class CoTask : public TaskBase {
|
||||
public:
|
||||
CoTask(ffrt_executor_task_type_t type, const task_attr_private *attr)
|
||||
: TaskBase(type, attr)
|
||||
{
|
||||
we.task = this;
|
||||
if (attr) {
|
||||
stack_size = std::max(attr->stackSize_, MIN_STACK_SIZE);
|
||||
}
|
||||
}
|
||||
~CoTask() override = default;
|
||||
|
||||
uint8_t func_storage[ffrt_auto_managed_function_storage_size]; // 函数闭包、指针或函数对象
|
||||
|
||||
std::string label;
|
||||
CoWakeType coWakeType { CoWakeType::NO_TIMEOUT_WAKE };
|
||||
int cpuBoostCtxId = -1;
|
||||
WaitEntry we; // Used on syncprimitive wait que
|
||||
WaitUntilEntry* wue = nullptr; // used on syncprimitive wait que and delayed wait que
|
||||
// lifecycle connection between task and coroutine is shown as below:
|
||||
// |*task pending*|*task ready*|*task executing*|*task done*|*task release*|
|
||||
// |**********coroutine*********|
|
||||
CoRoutine* coRoutine = nullptr;
|
||||
uint64_t stack_size = STACK_SIZE;
|
||||
std::atomic<pthread_t> runningTid = 0;
|
||||
int legacyCountNum = 0; // dynamic switch controlled by set_legacy_mode api
|
||||
std::mutex mutex_; // used in coroute
|
||||
std::condition_variable waitCond_; // cv for thread wait
|
||||
|
||||
bool pollerEnable = false; // set true if task call ffrt_epoll_ctl
|
||||
bool threadMode_ = false;
|
||||
std::string GetLabel() const override
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
inline void UnbindCoRoutione()
|
||||
{
|
||||
std::lock_guard lck(mutex_);
|
||||
coRoutine = nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
BlockType blockType { BlockType::BLOCK_COROUTINE }; // block type for lagacy mode changing
|
||||
};
|
||||
|
||||
std::string StatusToString(TaskStatus status);
|
||||
|
||||
void ExecuteTask(TaskBase* task);
|
||||
|
||||
inline bool IsCoTask(TaskBase* task)
|
||||
{
|
||||
return task && (task->type == ffrt_normal_task ||
|
||||
(task->type == ffrt_queue_task && (!reinterpret_cast<ffrt::CoTask*>(task)->threadMode_)));
|
||||
}
|
||||
|
||||
inline bool IncDeleteRefIfPositive(TaskBase* task)
|
||||
{
|
||||
uint32_t expected = task->rc.load();
|
||||
while (expected > 0) {
|
||||
if (task->rc.compare_exchange_weak(expected, expected + 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 TASK_FACTORY_HPP
|
||||
#define TASK_FACTORY_HPP
|
||||
|
||||
#include "tm/task_base.h"
|
||||
#include "util/cb_func.h"
|
||||
#include "util/slab.h"
|
||||
|
||||
namespace ffrt {
|
||||
template <typename T>
|
||||
class TaskFactory {
|
||||
public:
|
||||
static TaskFactory<T>& Instance();
|
||||
|
||||
static T* Alloc()
|
||||
{
|
||||
return Instance().alloc_();
|
||||
}
|
||||
|
||||
static void Free(T* task)
|
||||
{
|
||||
Instance().free_(task);
|
||||
}
|
||||
|
||||
static void Free_(T* task)
|
||||
{
|
||||
if (Instance().free__ != nullptr) {
|
||||
Instance().free__(task);
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<void*> GetUnfreedMem()
|
||||
{
|
||||
if (Instance().getUnfreedMem_ != nullptr) {
|
||||
return Instance().getUnfreedMem_();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static std::vector<void*> GetUnfreedTasksFiltered()
|
||||
{
|
||||
LockMem();
|
||||
std::vector<void*> unfreed = GetUnfreedMem();
|
||||
// Filter out tasks where the reference count increment failed.
|
||||
unfreed.erase(
|
||||
std::remove_if(unfreed.begin(), unfreed.end(),
|
||||
[](void* task) {
|
||||
return !IncDeleteRefIfPositive(reinterpret_cast<TaskBase*>(task));
|
||||
}),
|
||||
unfreed.end()
|
||||
);
|
||||
UnlockMem();
|
||||
return unfreed;
|
||||
}
|
||||
|
||||
static bool HasBeenFreed(T* task)
|
||||
{
|
||||
if (Instance().hasBeenFreed_ != nullptr) {
|
||||
return Instance().hasBeenFreed_(task);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void LockMem()
|
||||
{
|
||||
if (Instance().lockMem_ != nullptr) {
|
||||
Instance().lockMem_();
|
||||
}
|
||||
}
|
||||
|
||||
static void UnlockMem()
|
||||
{
|
||||
if (Instance().unlockMem_ != nullptr) {
|
||||
Instance().unlockMem_();
|
||||
}
|
||||
}
|
||||
|
||||
static void RegistCb(
|
||||
typename TaskAllocCB<T>::Alloc &&alloc,
|
||||
typename TaskAllocCB<T>::Free &&free,
|
||||
typename TaskAllocCB<T>::Free_ &&free_ = nullptr,
|
||||
typename TaskAllocCB<T>::GetUnfreedMem &&getUnfreedMem = nullptr,
|
||||
typename TaskAllocCB<T>::HasBeenFreed &&hasBeenFreed = nullptr,
|
||||
typename TaskAllocCB<T>::LockMem &&lockMem = nullptr,
|
||||
typename TaskAllocCB<T>::UnlockMem &&unlockMem = nullptr)
|
||||
{
|
||||
Instance().alloc_ = std::move(alloc);
|
||||
Instance().free_ = std::move(free);
|
||||
Instance().free__ = std::move(free_);
|
||||
Instance().getUnfreedMem_ = std::move(getUnfreedMem);
|
||||
Instance().hasBeenFreed_ = std::move(hasBeenFreed);
|
||||
Instance().lockMem_ = std::move(lockMem);
|
||||
Instance().unlockMem_ = std::move(unlockMem);
|
||||
}
|
||||
|
||||
private:
|
||||
typename TaskAllocCB<T>::Alloc alloc_;
|
||||
typename TaskAllocCB<T>::Free free_;
|
||||
typename TaskAllocCB<T>::Free_ free__;
|
||||
typename TaskAllocCB<T>::GetUnfreedMem getUnfreedMem_;
|
||||
typename TaskAllocCB<T>::HasBeenFreed hasBeenFreed_;
|
||||
typename TaskAllocCB<T>::LockMem lockMem_;
|
||||
typename TaskAllocCB<T>::UnlockMem unlockMem_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TaskMemScopedLock {
|
||||
public:
|
||||
TaskMemScopedLock()
|
||||
{
|
||||
TaskFactory<T>::LockMem();
|
||||
}
|
||||
|
||||
~TaskMemScopedLock()
|
||||
{
|
||||
TaskFactory<T>::UnlockMem();
|
||||
}
|
||||
};
|
||||
} // namespace ffrt
|
||||
|
||||
#endif
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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 UV_TASK_H_
|
||||
#define UV_TASK_H_
|
||||
|
||||
#include "task_base.h"
|
||||
#include "c/executor_task.h"
|
||||
#include "core/task_io.h"
|
||||
#include "core/task_attr_private.h"
|
||||
#include "tm/task_factory.h"
|
||||
#ifdef USE_OHOS_QOS
|
||||
#include "qos.h"
|
||||
#else
|
||||
#include "staging_qos/sched/qos.h"
|
||||
#endif
|
||||
|
||||
namespace ffrt {
|
||||
class UVTask : public TaskBase {
|
||||
public:
|
||||
UVTask(ffrt_executor_task* uvWork, const task_attr_private *attr)
|
||||
: TaskBase(ffrt_uv_task, attr), uvWork(uvWork)
|
||||
{
|
||||
/*
|
||||
uvWork是libuv传进来的ffrt_executor_task指针,其中的wq成员为双向链表节点,和LinkedList的内存布局一致,
|
||||
曾经用于软化队列的节点和TaskBase类一样插入ReadyQueue。
|
||||
目前由于已组合进入UVTask类型,不再作为链表节点,此处就可以使用uvWorker的wq来标记任务是否已经出队的状态。
|
||||
libuv里面,在cancel时也会判断任务是否已经出队(uv__queue_empty):
|
||||
q== q->next || q != q->next->prev;其中next对应wq[0],prev对应wq[1]
|
||||
将wq入队,即可满足v__queue_empty返回false的需要
|
||||
*/
|
||||
if (uvWork != nullptr) {
|
||||
uvWorkList.PushBack(reinterpret_cast<LinkedList*>(&uvWork->wq));
|
||||
} else {
|
||||
FFRT_LOGE("executor_task is nullptr");
|
||||
}
|
||||
}
|
||||
ffrt_executor_task* uvWork;
|
||||
|
||||
void Prepare() override {}
|
||||
|
||||
void Ready() override;
|
||||
|
||||
void Pop() override
|
||||
{
|
||||
SetStatus(TaskStatus::POPPED);
|
||||
}
|
||||
|
||||
void Execute() override;
|
||||
|
||||
BlockType Block() override
|
||||
{
|
||||
SetStatus(TaskStatus::THREAD_BLOCK);
|
||||
return BlockType::BLOCK_THREAD;
|
||||
}
|
||||
|
||||
void Wake() override
|
||||
{
|
||||
SetStatus(TaskStatus::EXECUTING);
|
||||
}
|
||||
|
||||
void Finish() override {}
|
||||
void Cancel() override {}
|
||||
|
||||
void FreeMem() override
|
||||
{
|
||||
TaskFactory<UVTask>::Free(this);
|
||||
}
|
||||
|
||||
void SetQos(const QoS& newQos) override
|
||||
{
|
||||
qos_ = newQos;
|
||||
}
|
||||
|
||||
std::string GetLabel() const override
|
||||
{
|
||||
return "uv-task";
|
||||
}
|
||||
|
||||
BlockType GetBlockType() const override
|
||||
{
|
||||
return BlockType::BLOCK_THREAD;
|
||||
}
|
||||
|
||||
inline void SetDequeued()
|
||||
{
|
||||
if (uvWork == nullptr) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
uvWork是libuv传进来的ffrt_executor_task指针,其中的wq成员为双向链表节点,和LinkedList的内存布局一致,
|
||||
曾经用于软化队列的节点和TaskBase类一样插入ReadyQueue。
|
||||
目前由于已组合进入UVTask类型,不再作为链表节点,此处就可以使用uvWorker的wq来标记任务是否已经出队的状态。
|
||||
libuv里面,在cancel时也会判断任务是否已经出队(uv__queue_empty):
|
||||
q== q->next || q != q->next->prev;其中next对应wq[0],prev对应wq[1]
|
||||
将wq出队,即可满足v__queue_empty返回false的需要
|
||||
*/
|
||||
LinkedList::RemoveCur(reinterpret_cast<LinkedList*>(&uvWork->wq));
|
||||
}
|
||||
|
||||
static void ExecuteImpl(UVTask* task, ffrt_executor_task_func func);
|
||||
private:
|
||||
LinkedList uvWorkList;
|
||||
};
|
||||
} /* namespace ffrt */
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_CB_FUNC_H_
|
||||
#define FFRT_CB_FUNC_H_
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
struct SingleInsCB {
|
||||
using Instance = std::function<T &()>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct TaskAllocCB {
|
||||
using Alloc = std::function<T *()>;
|
||||
using Free = std::function<void (T *)>;
|
||||
using Free_ = std::function<void (T *)>;
|
||||
using GetUnfreedMem = std::function<std::vector<void *> ()>;
|
||||
using HasBeenFreed = std::function<bool (T *)>;
|
||||
using LockMem = std::function<void ()>;
|
||||
using UnlockMem = std::function<void ()>;
|
||||
};
|
||||
|
||||
#endif /* FFRT_CB_FUNC_H_ */
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 UTIL_FFRTFACADE_HPP
|
||||
#define UTIL_FFRTFACADE_HPP
|
||||
#include "sched/scheduler.h"
|
||||
#include "eu/co_routine.h"
|
||||
#include "eu/execute_unit.h"
|
||||
#include "dm/dependence_manager.h"
|
||||
#include "queue/queue_monitor.h"
|
||||
#include "sync/delayed_worker.h"
|
||||
#include "eu/io_poller.h"
|
||||
#include "sync/timer_manager.h"
|
||||
#include "util/worker_monitor.h"
|
||||
|
||||
namespace ffrt {
|
||||
bool GetExitFlag();
|
||||
std::shared_mutex& GetExitMtx();
|
||||
const char* GetCurrentProcessName();
|
||||
|
||||
class FFRTFacade {
|
||||
public:
|
||||
static inline ExecuteUnit& GetEUInstance()
|
||||
{
|
||||
return Instance().GetEUInstanceImpl();
|
||||
}
|
||||
|
||||
static inline DependenceManager& GetDMInstance()
|
||||
{
|
||||
return Instance().GetDMInstanceImpl();
|
||||
}
|
||||
|
||||
static inline IOPoller& GetPPInstance()
|
||||
{
|
||||
return Instance().GetPPInstanceImpl();
|
||||
}
|
||||
|
||||
static inline TimerManager& GetTMInstance()
|
||||
{
|
||||
return Instance().GetTMInstanceImpl();
|
||||
}
|
||||
|
||||
static inline DelayedWorker& GetDWInstance()
|
||||
{
|
||||
return Instance().GetDWInstanceImpl();
|
||||
}
|
||||
|
||||
static inline Scheduler* GetSchedInstance()
|
||||
{
|
||||
return Instance().GetSchedInstanceImpl();
|
||||
}
|
||||
|
||||
static inline CoStackAttr* GetCSAInstance()
|
||||
{
|
||||
return Instance().GetCSAInstanceImpl();
|
||||
}
|
||||
|
||||
static inline QueueMonitor& GetQMInstance()
|
||||
{
|
||||
return Instance().GetQMInstanceImpl();
|
||||
}
|
||||
|
||||
static inline WorkerMonitor& GetWMInstance()
|
||||
{
|
||||
return Instance().GetWMInstanceImpl();
|
||||
}
|
||||
|
||||
private:
|
||||
FFRTFacade();
|
||||
|
||||
static FFRTFacade& Instance()
|
||||
{
|
||||
static FFRTFacade facade;
|
||||
return facade;
|
||||
}
|
||||
|
||||
inline ExecuteUnit& GetEUInstanceImpl()
|
||||
{
|
||||
return ExecuteUnit::Instance();
|
||||
}
|
||||
|
||||
inline DependenceManager& GetDMInstanceImpl()
|
||||
{
|
||||
return DependenceManager::Instance();
|
||||
}
|
||||
|
||||
inline IOPoller& GetPPInstanceImpl()
|
||||
{
|
||||
return IOPoller::Instance();
|
||||
}
|
||||
|
||||
inline TimerManager& GetTMInstanceImpl()
|
||||
{
|
||||
return TimerManager::Instance();
|
||||
}
|
||||
|
||||
inline DelayedWorker& GetDWInstanceImpl()
|
||||
{
|
||||
return DelayedWorker::GetInstance();
|
||||
}
|
||||
|
||||
inline Scheduler* GetSchedInstanceImpl()
|
||||
{
|
||||
return Scheduler::Instance();
|
||||
}
|
||||
|
||||
inline CoStackAttr* GetCSAInstanceImpl()
|
||||
{
|
||||
return CoStackAttr::Instance();
|
||||
}
|
||||
|
||||
inline QueueMonitor& GetQMInstanceImpl()
|
||||
{
|
||||
return QueueMonitor::GetInstance();
|
||||
}
|
||||
|
||||
inline WorkerMonitor& GetWMInstanceImpl()
|
||||
{
|
||||
return WorkerMonitor::GetInstance();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace FFRT
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_RING_BUFFER_H
|
||||
#define FFRT_RING_BUFFER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <securec.h>
|
||||
|
||||
namespace ffrt {
|
||||
|
||||
class FFRTRingBuffer {
|
||||
public:
|
||||
FFRTRingBuffer(char *buf, uint32_t len) : buf_(buf), bufferLen_(len), writtenSize_(0)
|
||||
{
|
||||
memset_s(buf_, bufferLen_, 0, bufferLen_);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int Write(T data)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(bufferMutex_);
|
||||
if (writtenSize_ + sizeof(T) > bufferLen_) {
|
||||
writtenSize_ = sizeof(T);
|
||||
return memcpy_s(buf_, bufferLen_, &data, sizeof(T));
|
||||
} else {
|
||||
int ret = memcpy_s(buf_ + writtenSize_, bufferLen_ - writtenSize_, &data, sizeof(T));
|
||||
writtenSize_ += sizeof(T);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
char *GetBuffer()
|
||||
{
|
||||
return buf_;
|
||||
}
|
||||
|
||||
uint32_t GetBufferSize()
|
||||
{
|
||||
return bufferLen_;
|
||||
}
|
||||
|
||||
private:
|
||||
char *buf_;
|
||||
uint32_t bufferLen_;
|
||||
uint32_t writtenSize_;
|
||||
std::mutex bufferMutex_;
|
||||
};
|
||||
}
|
||||
#endif // FFRT_RING_BUFFER_H
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 __GRAPH_CHECK_H__
|
||||
#define __GRAPH_CHECK_H__
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
namespace ffrt {
|
||||
struct VertexStatus {
|
||||
bool visited;
|
||||
bool recStack;
|
||||
};
|
||||
|
||||
class GraphCheckCyclic {
|
||||
std::map<uint64_t, std::list<uint64_t>> vetexes;
|
||||
bool IsCyclicDfs(uint64_t v, std::map<uint64_t, struct VertexStatus>& vertexStatus);
|
||||
public:
|
||||
void AddVetexByLabel(uint64_t label);
|
||||
void AddEdgeByLabel(uint64_t startLabel, uint64_t endLabel);
|
||||
void RemoveEdgeByLabel(uint64_t endLabel);
|
||||
uint32_t EdgeNum(void);
|
||||
uint32_t VertexNum(void) const;
|
||||
bool IsCyclic();
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_LINKED_LIST_H
|
||||
#define FFRT_LINKED_LIST_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ffrt {
|
||||
class LinkedList {
|
||||
public:
|
||||
LinkedList() : prev(this), next(this)
|
||||
{
|
||||
}
|
||||
|
||||
LinkedList(LinkedList* prev, LinkedList* next) : prev(prev), next(next)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static ptrdiff_t OffsetOf(LinkedList T::*member) noexcept
|
||||
{
|
||||
return reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<T*>(0)->*member));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T* ContainerOf(LinkedList* node, LinkedList T::*member) noexcept
|
||||
{
|
||||
return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(node) - OffsetOf<T>(member));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* ContainerOf(LinkedList T::*member) noexcept
|
||||
{
|
||||
return ContainerOf(this, member);
|
||||
}
|
||||
|
||||
static void InsertAfter(LinkedList* cur, LinkedList* node) noexcept
|
||||
{
|
||||
node->next = cur->next;
|
||||
node->prev = cur;
|
||||
cur->next->prev = node;
|
||||
cur->next = node;
|
||||
}
|
||||
|
||||
static void InsertBefore(LinkedList* cur, LinkedList* node) noexcept
|
||||
{
|
||||
node->next = cur;
|
||||
node->prev = cur->prev;
|
||||
cur->prev->next = node;
|
||||
cur->prev = node;
|
||||
}
|
||||
|
||||
static void Delete(LinkedList& node) noexcept
|
||||
{
|
||||
node.prev->next = node.next;
|
||||
node.next->prev = node.prev;
|
||||
node.next = &node;
|
||||
node.prev = &node;
|
||||
}
|
||||
|
||||
static void Delete(LinkedList* node) noexcept
|
||||
{
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
node->next = node;
|
||||
node->prev = node;
|
||||
}
|
||||
|
||||
static void RemoveCur(LinkedList& node) noexcept
|
||||
{
|
||||
if (node.Null()) {
|
||||
return;
|
||||
}
|
||||
Delete(node);
|
||||
}
|
||||
|
||||
static void RemoveCur(LinkedList* node) noexcept
|
||||
{
|
||||
if (node->Null()) {
|
||||
return;
|
||||
}
|
||||
Delete(node);
|
||||
}
|
||||
|
||||
static LinkedList* Next(LinkedList* cur) noexcept
|
||||
{
|
||||
if (cur->Empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinkedList* next = cur->next;
|
||||
return next;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T* Next(LinkedList* cur, LinkedList T::*member) noexcept
|
||||
{
|
||||
if (cur->Empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinkedList* next = cur->next;
|
||||
return ContainerOf<T>(next, member);
|
||||
}
|
||||
|
||||
static LinkedList* RemoveNext(LinkedList* cur) noexcept
|
||||
{
|
||||
if (cur->Empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinkedList* next = cur->next;
|
||||
Delete(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T* RemoveNext(LinkedList* cur, LinkedList T::*member) noexcept
|
||||
{
|
||||
if (cur->Empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinkedList* next = cur->next;
|
||||
Delete(next);
|
||||
return ContainerOf<T>(next, member);
|
||||
}
|
||||
|
||||
static LinkedList* RemovePrev(LinkedList* cur) noexcept
|
||||
{
|
||||
if (cur->Empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinkedList* prev = cur->prev;
|
||||
Delete(prev);
|
||||
return prev;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T* RemovePrev(LinkedList* cur, LinkedList T::*member) noexcept
|
||||
{
|
||||
if (cur->Empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinkedList* prev = cur->prev;
|
||||
Delete(prev);
|
||||
return ContainerOf<T>(prev, member);
|
||||
}
|
||||
|
||||
void InsertAfter(LinkedList& node) noexcept
|
||||
{
|
||||
InsertAfter(this, &node);
|
||||
}
|
||||
|
||||
void InsertAfter(LinkedList* node) noexcept
|
||||
{
|
||||
InsertAfter(this, node);
|
||||
}
|
||||
|
||||
void InsertBefore(LinkedList& node) noexcept
|
||||
{
|
||||
InsertBefore(this, &node);
|
||||
}
|
||||
|
||||
void InsertBefore(LinkedList* node) noexcept
|
||||
{
|
||||
InsertBefore(this, node);
|
||||
}
|
||||
|
||||
LinkedList* Next() noexcept
|
||||
{
|
||||
return Next(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* Next(LinkedList T::*member) noexcept
|
||||
{
|
||||
return Next(this, member);
|
||||
}
|
||||
|
||||
LinkedList* RemoveNext() noexcept
|
||||
{
|
||||
return RemoveNext(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* RemoveNext(LinkedList T::*member) noexcept
|
||||
{
|
||||
return RemoveNext(this, member);
|
||||
}
|
||||
|
||||
LinkedList* RemovePrev() noexcept
|
||||
{
|
||||
return RemovePrev(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* RemovePrev(LinkedList T::*member) noexcept
|
||||
{
|
||||
return RemovePrev(this, member);
|
||||
}
|
||||
|
||||
void PushFront(LinkedList& node) noexcept
|
||||
{
|
||||
InsertAfter(&node);
|
||||
}
|
||||
|
||||
void PushFront(LinkedList* node) noexcept
|
||||
{
|
||||
InsertAfter(node);
|
||||
}
|
||||
|
||||
void PushBack(LinkedList& node) noexcept
|
||||
{
|
||||
InsertBefore(&node);
|
||||
}
|
||||
|
||||
void PushBack(LinkedList* node) noexcept
|
||||
{
|
||||
InsertBefore(node);
|
||||
}
|
||||
|
||||
LinkedList* Front() noexcept
|
||||
{
|
||||
return Next();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* Front(LinkedList T::*member) noexcept
|
||||
{
|
||||
return Next(member);
|
||||
}
|
||||
|
||||
LinkedList* PopFront() noexcept
|
||||
{
|
||||
return RemoveNext();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* PopFront(LinkedList T::*member) noexcept
|
||||
{
|
||||
return RemoveNext(member);
|
||||
}
|
||||
|
||||
LinkedList* PopBack() noexcept
|
||||
{
|
||||
return RemovePrev();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* PopBack(LinkedList T::*member) noexcept
|
||||
{
|
||||
return RemovePrev(member);
|
||||
}
|
||||
|
||||
bool Empty() const noexcept
|
||||
{
|
||||
return next == this;
|
||||
}
|
||||
|
||||
bool Null() const noexcept
|
||||
{
|
||||
return prev == nullptr && next == nullptr;
|
||||
}
|
||||
|
||||
bool InList() const noexcept
|
||||
{
|
||||
return (next != nullptr && next != this);
|
||||
}
|
||||
|
||||
void PushBack(LinkedList& first, LinkedList& last) noexcept
|
||||
{
|
||||
// push back multiple linked nodes to list
|
||||
last.next = this;
|
||||
first.prev = this->prev;
|
||||
this->prev->next = &first;
|
||||
this->prev = &last;
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedList* prev;
|
||||
LinkedList* next;
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 _REF_FUNCTION_HEADER_H_
|
||||
#define _REF_FUNCTION_HEADER_H_
|
||||
|
||||
#include <atomic>
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
#include "c/type_def.h"
|
||||
|
||||
namespace ffrt {
|
||||
enum FuncHeaderStatus {
|
||||
NOT_SUBMIT = 1,
|
||||
ALREADY_SUBMIT = 2,
|
||||
};
|
||||
|
||||
void DestroyFunctionWrapper(ffrt_function_header_t* f, ffrt_function_kind_t kind);
|
||||
|
||||
class RefFunctionHeader {
|
||||
public:
|
||||
RefFunctionHeader(ffrt_function_header_t* header) : functionHeader_(header) {}
|
||||
bool IncDeleteRef()
|
||||
{
|
||||
uint16_t exp = NOT_SUBMIT;
|
||||
uint16_t des = ALREADY_SUBMIT;
|
||||
return rc.compare_exchange_strong(exp, des, std::memory_order_relaxed);
|
||||
}
|
||||
void DecDeleteRef()
|
||||
{
|
||||
auto v = rc.fetch_sub(1);
|
||||
if (v == 1) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
ffrt_function_header_t* functionHeader_ = nullptr;
|
||||
std::atomic_uint16_t rc = 1;
|
||||
private:
|
||||
~RefFunctionHeader()
|
||||
{
|
||||
ffrt::DestroyFunctionWrapper(functionHeader_, ffrt_function_kind_general);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 UTIL_SLAB_HPP
|
||||
#define UTIL_SLAB_HPP
|
||||
|
||||
#include <new>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
#include <securec.h>
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
#include <unordered_set>
|
||||
#endif
|
||||
#include <sys/mman.h>
|
||||
#include "sync/sync.h"
|
||||
#include "dfx/log/ffrt_log_api.h"
|
||||
|
||||
namespace ffrt {
|
||||
const std::size_t BatchAllocSize = 32 * 1024;
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
constexpr uint32_t ALLOCATOR_DESTRUCT_TIMESOUT = 1000;
|
||||
#endif
|
||||
|
||||
#ifndef FFRT_ALLOCATOR_MMAP_SIZE
|
||||
#define FFRT_ALLOCATOR_MMAP_SIZE (8 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
template <typename T, size_t MmapSz = BatchAllocSize>
|
||||
class SimpleAllocator {
|
||||
public:
|
||||
SimpleAllocator(const SimpleAllocator&) = delete;
|
||||
SimpleAllocator(SimpleAllocator&&) = delete;
|
||||
SimpleAllocator& operator=(const SimpleAllocator&) = delete;
|
||||
SimpleAllocator& operator=(SimpleAllocator&&) = delete;
|
||||
fast_mutex lock;
|
||||
|
||||
static SimpleAllocator<T>* Instance(std::size_t size = sizeof(T))
|
||||
{
|
||||
static SimpleAllocator<T> ins(size);
|
||||
return &ins;
|
||||
}
|
||||
|
||||
// NOTE: call constructor after AllocMem
|
||||
static T* AllocMem()
|
||||
{
|
||||
return Instance()->Alloc();
|
||||
}
|
||||
|
||||
// NOTE: call destructor before FreeMem
|
||||
static void FreeMem(T* t)
|
||||
{
|
||||
// unlock()内部lck记录锁的状态为非持有状态,析构时访问状态变量为非持有状态,则不访问实际持有的mutex
|
||||
// return之前的lck析构不产生UAF问题,因为return之前随着root析构,锁的内存被释放
|
||||
t->~T();
|
||||
Instance()->free(t);
|
||||
}
|
||||
|
||||
static void FreeMem_(T* t)
|
||||
{
|
||||
Instance()->free_(t);
|
||||
}
|
||||
|
||||
// only used for BBOX
|
||||
static std::vector<void *> getUnfreedMem()
|
||||
{
|
||||
return Instance()->getUnfreed();
|
||||
}
|
||||
|
||||
static bool HasBeenFreed(T* t)
|
||||
{
|
||||
return Instance()->BeenFreed(t);
|
||||
}
|
||||
|
||||
static void LockMem()
|
||||
{
|
||||
return Instance()->SimpleAllocatorLock();
|
||||
}
|
||||
|
||||
static void UnlockMem()
|
||||
{
|
||||
return Instance()->SimpleAllocatorUnLock();
|
||||
}
|
||||
private:
|
||||
std::deque<T*> primaryCache;
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
std::unordered_set<T*> secondaryCache;
|
||||
#endif
|
||||
std::size_t TSize;
|
||||
T* basePtr = nullptr;
|
||||
std::size_t count = 0;
|
||||
|
||||
std::vector<void *> getUnfreed()
|
||||
{
|
||||
std::vector<void *> ret;
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
ret.reserve(MmapSz / TSize + secondaryCache.size());
|
||||
char* p = reinterpret_cast<char*>(basePtr);
|
||||
for (std::size_t i = 0; i + TSize <= MmapSz; i += TSize) {
|
||||
if (basePtr != nullptr &&
|
||||
std::find(primaryCache.begin(), primaryCache.end(),
|
||||
reinterpret_cast<T*>(p + i)) == primaryCache.end()) {
|
||||
ret.push_back(reinterpret_cast<void *>(p + i));
|
||||
}
|
||||
}
|
||||
for (auto ite = secondaryCache.cbegin(); ite != secondaryCache.cend(); ite++) {
|
||||
ret.push_back(reinterpret_cast<void *>(*ite));
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool BeenFreed(T* t)
|
||||
{
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
if (t == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (basePtr != nullptr &&
|
||||
basePtr <= t &&
|
||||
static_cast<size_t>(reinterpret_cast<uintptr_t>(t)) <
|
||||
(static_cast<size_t>(reinterpret_cast<uintptr_t>(basePtr)) + MmapSz)) {
|
||||
return std::find(primaryCache.begin(), primaryCache.end(), t) != primaryCache.end();
|
||||
} else {
|
||||
return secondaryCache.find(t) == secondaryCache.end();
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimpleAllocatorLock()
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
void SimpleAllocatorUnLock()
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
char* p = reinterpret_cast<char*>(std::calloc(1, MmapSz));
|
||||
FFRT_COND_TERMINATE((p == nullptr), "p calloc failed");
|
||||
count = MmapSz / TSize;
|
||||
for (std::size_t i = 0; i + TSize <= MmapSz; i += TSize) {
|
||||
primaryCache.push_back(reinterpret_cast<T*>(p + i));
|
||||
}
|
||||
basePtr = reinterpret_cast<T*>(p);
|
||||
}
|
||||
|
||||
T* Alloc()
|
||||
{
|
||||
std::lock_guard<decltype(lock)> lk(lock);
|
||||
T* t = nullptr;
|
||||
if (count == 0) {
|
||||
if (basePtr != nullptr) {
|
||||
t = reinterpret_cast<T*>(std::calloc(1, TSize));
|
||||
FFRT_COND_TERMINATE((t == nullptr), "t calloc failed");
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
secondaryCache.insert(t);
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
init();
|
||||
}
|
||||
t = primaryCache.front();
|
||||
primaryCache.pop_front();
|
||||
count--;
|
||||
return t;
|
||||
}
|
||||
|
||||
void free(T* t)
|
||||
{
|
||||
std::lock_guard<decltype(lock)> lk(lock);
|
||||
if (basePtr != nullptr &&
|
||||
basePtr <= t &&
|
||||
static_cast<size_t>(reinterpret_cast<uintptr_t>(t)) <
|
||||
static_cast<size_t>(reinterpret_cast<uintptr_t>(basePtr)) + MmapSz) {
|
||||
primaryCache.push_back(t);
|
||||
count++;
|
||||
} else {
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
secondaryCache.erase(t);
|
||||
#endif
|
||||
std::free(t);
|
||||
}
|
||||
}
|
||||
|
||||
void free_(T* t)
|
||||
{
|
||||
std::lock_guard<decltype(lock)> lk(lock);
|
||||
if (basePtr != nullptr && basePtr <= t && static_cast<size_t>(reinterpret_cast<uintptr_t>(t)) <
|
||||
static_cast<size_t>(reinterpret_cast<uintptr_t>(basePtr)) + MmapSz) {
|
||||
primaryCache.push_back(t);
|
||||
count++;
|
||||
} else {
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
secondaryCache.erase(t);
|
||||
#endif
|
||||
std::free(t);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleAllocator(std::size_t size = sizeof(T)) : TSize(size)
|
||||
{
|
||||
}
|
||||
~SimpleAllocator()
|
||||
{
|
||||
std::unique_lock<decltype(lock)> lck(lock);
|
||||
if (basePtr == nullptr) {
|
||||
return;
|
||||
}
|
||||
#ifdef FFRT_BBOX_ENABLE
|
||||
uint32_t try_cnt = ALLOCATOR_DESTRUCT_TIMESOUT;
|
||||
std::size_t reserved = MmapSz / TSize;
|
||||
while (try_cnt > 0) {
|
||||
if (primaryCache.size() == reserved && secondaryCache.size() == 0) {
|
||||
break;
|
||||
}
|
||||
lck.unlock();
|
||||
usleep(1000);
|
||||
try_cnt--;
|
||||
lck.lock();
|
||||
}
|
||||
if (try_cnt == 0) {
|
||||
FFRT_LOGE("clear allocator failed");
|
||||
}
|
||||
for (auto ite = secondaryCache.cbegin(); ite != secondaryCache.cend(); ite++) {
|
||||
std::free(*ite);
|
||||
}
|
||||
#endif
|
||||
std::free(basePtr);
|
||||
FFRT_LOGI("destruct SimpleAllocator");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, std::size_t MmapSz = FFRT_ALLOCATOR_MMAP_SIZE>
|
||||
class QSimpleAllocator {
|
||||
std::size_t TSize;
|
||||
std::size_t curAllocated;
|
||||
std::size_t maxAllocated;
|
||||
std::mutex lock;
|
||||
std::vector<T*> cache;
|
||||
uint32_t flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
|
||||
bool expand()
|
||||
{
|
||||
const int prot = PROT_READ | PROT_WRITE;
|
||||
char* p = reinterpret_cast<char*>(mmap(nullptr, MmapSz, prot, flags, -1, 0));
|
||||
if (p == (char*)MAP_FAILED) {
|
||||
if ((flags & MAP_HUGETLB) != 0) {
|
||||
flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
p = reinterpret_cast<char*>(mmap(nullptr, MmapSz, prot, flags, -1, 0));
|
||||
}
|
||||
if (p == (char*)MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (std::size_t i = 0; i + TSize <= MmapSz; i += TSize) {
|
||||
cache.push_back(reinterpret_cast<T*>(p + i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
T* Alloc()
|
||||
{
|
||||
T* p = nullptr;
|
||||
std::lock_guard<decltype(lock)> lk(lock);
|
||||
if (cache.empty()) {
|
||||
if (!expand()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
p = cache.back();
|
||||
++curAllocated;
|
||||
maxAllocated = std::max(curAllocated, maxAllocated);
|
||||
cache.pop_back();
|
||||
return p;
|
||||
}
|
||||
|
||||
void free(T* p)
|
||||
{
|
||||
std::lock_guard<decltype(lock)> lk(lock);
|
||||
--curAllocated;
|
||||
cache.push_back(p);
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
T* p = nullptr;
|
||||
std::lock_guard<decltype(lock)> lk(lock);
|
||||
FFRT_LOGD("coroutine release with waterline %d, cur occupied %d, cached size %d",
|
||||
maxAllocated, curAllocated, cache.size());
|
||||
size_t reservedCnt = maxAllocated - curAllocated + 1; // reserve additional one for robustness
|
||||
maxAllocated = curAllocated;
|
||||
while (cache.size() > reservedCnt) {
|
||||
p = cache.back();
|
||||
cache.pop_back();
|
||||
int ret = munmap(p, TSize);
|
||||
if (ret != 0) {
|
||||
FFRT_LOGE("munmap failed with errno: %d", errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QSimpleAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
explicit QSimpleAllocator(std::size_t size = sizeof(T)) : curAllocated(0), maxAllocated(0)
|
||||
{
|
||||
std::size_t p_size = static_cast<std::size_t>(getpagesize());
|
||||
// manually align the size to the page size
|
||||
TSize = (size - 1 + p_size) & -p_size;
|
||||
if (MmapSz % TSize != 0) {
|
||||
FFRT_LOGE("MmapSz is not divisible by TSize which may cause memory leak!");
|
||||
}
|
||||
}
|
||||
QSimpleAllocator(QSimpleAllocator const&) = delete;
|
||||
void operator=(QSimpleAllocator const&) = delete;
|
||||
|
||||
static QSimpleAllocator<T, MmapSz>* Instance(std::size_t size)
|
||||
{
|
||||
static QSimpleAllocator<T, MmapSz> ins(size);
|
||||
return &ins;
|
||||
}
|
||||
|
||||
static T* AllocMem(std::size_t size = sizeof(T))
|
||||
{
|
||||
return Instance(size)->Alloc();
|
||||
}
|
||||
|
||||
static void FreeMem(T* p, std::size_t size = sizeof(T))
|
||||
{
|
||||
Instance(size)->free(p);
|
||||
}
|
||||
|
||||
static void releaseMem(std::size_t size = sizeof(T))
|
||||
{
|
||||
Instance(size)->release();
|
||||
}
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif /* UTIL_SLAB_H */
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_SPMC_QUEUE_H
|
||||
#define FFRT_SPMC_QUEUE_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace ffrt {
|
||||
class SpmcQueue {
|
||||
public:
|
||||
~SpmcQueue();
|
||||
|
||||
unsigned int GetLength() const;
|
||||
unsigned int GetCapacity() const;
|
||||
|
||||
/**
|
||||
* @brief 初始化队列。
|
||||
* @param capacity 队列容量。
|
||||
* @retval 成功返回0,失败返回-1。
|
||||
*/
|
||||
int Init(unsigned int capacity);
|
||||
|
||||
/**
|
||||
* @brief 取出队列首部元素。
|
||||
* @retval 指向首部元素的指针,若队列为空则返回nullptr。
|
||||
*/
|
||||
void* PopHead();
|
||||
|
||||
/**
|
||||
* @brief 将元素推入队列尾部。
|
||||
* @param object 要推入队列的元素。
|
||||
* @retval 成功返回0,失败返回-1。
|
||||
*/
|
||||
int PushTail(void* object);
|
||||
|
||||
/**
|
||||
* @brief 从队列首部批量取出元素后将元素批量推入目标队列尾部。
|
||||
* @param dstQueue 目标队列。
|
||||
* @param elementNum 取出元素数量。
|
||||
* @param qos 全局队列qos等级。
|
||||
* @param func 元素入队操作。
|
||||
* @retval 返回被推入队列尾部的元素数量。
|
||||
*/
|
||||
using PushFunc = void(*)(void*);
|
||||
unsigned int PopHeadToAnotherQueue(SpmcQueue& dstQueue, unsigned int elementNum, PushFunc func);
|
||||
|
||||
private:
|
||||
void** buf_ = nullptr;
|
||||
unsigned int capacity_ = 0;
|
||||
std::atomic<unsigned int> head_ {0};
|
||||
std::atomic<unsigned int> tail_ {0};
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 UTIL_TIME_FORMAT_H
|
||||
#define UTIL_TIME_FORMAT_H
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "internal_inc/types.h"
|
||||
|
||||
namespace ffrt {
|
||||
typedef enum {
|
||||
MILLISECOND,
|
||||
MICROSECOND,
|
||||
} TimeUnitT;
|
||||
|
||||
std::string FormatDateString4SystemClock(const std::chrono::system_clock::time_point& timePoint,
|
||||
TimeUnitT timeUnit = MILLISECOND);
|
||||
std::string FormatDateString4SteadyClock(uint64_t steadyClockTimeStamp, TimeUnitT timeUnit = MILLISECOND);
|
||||
std::string FormatDateString4CntCt(uint64_t cntCtTimeStamp, TimeUnitT timeUnit = MILLISECOND);
|
||||
std::string FormatDateToString(uint64_t timeStamp);
|
||||
uint64_t Arm64CntFrq(void);
|
||||
uint64_t Arm64CntCt(void);
|
||||
uint64_t TimeStampCntvct();
|
||||
uint64_t ConvertCntvctToUs(uint64_t cntCt);
|
||||
uint64_t ConvertUsToCntvct(uint64_t time);
|
||||
uint64_t ConvertTscToSteadyClockCount(uint64_t cntCt);
|
||||
std::string StatusToString(TaskStatus status);
|
||||
|
||||
inline uint64_t TimeStamp(void)
|
||||
{
|
||||
#if defined(__aarch64__)
|
||||
uint64_t tsc = 1;
|
||||
asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));
|
||||
return tsc;
|
||||
#else
|
||||
return static_cast<uint64_t>(std::chrono::time_point_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now()).time_since_epoch().count());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // UTIL_TIME_FORAMT_H
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_WORKER_MONITOR_H
|
||||
#define FFRT_WORKER_MONITOR_H
|
||||
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
#include <map>
|
||||
#include "eu/cpu_worker.h"
|
||||
#include "tm/task_base.h"
|
||||
|
||||
namespace ffrt {
|
||||
struct TaskTimeoutInfo {
|
||||
TaskBase* task_ = nullptr;
|
||||
int recordLevel_ = 0;
|
||||
int sampledTimes_ = 0;
|
||||
int executionTime_ = 0;
|
||||
|
||||
TaskTimeoutInfo() {}
|
||||
explicit TaskTimeoutInfo(TaskBase* task) : task_(task) {}
|
||||
};
|
||||
|
||||
struct CoWorkerInfo {
|
||||
size_t qosLevel_;
|
||||
int coWorkerCount_;
|
||||
int executionNum_;
|
||||
int sleepingWorkerNum_;
|
||||
|
||||
CoWorkerInfo(size_t qosLevel, int coWorkerCount, int executionNum, int sleepingWorkerNum)
|
||||
: qosLevel_(qosLevel), coWorkerCount_(coWorkerCount),
|
||||
executionNum_(executionNum), sleepingWorkerNum_(sleepingWorkerNum) {}
|
||||
};
|
||||
|
||||
struct WorkerInfo {
|
||||
int tid_;
|
||||
uint64_t gid_;
|
||||
uintptr_t workerTaskType_;
|
||||
std::string label_;
|
||||
|
||||
WorkerInfo(int workerId, uint64_t taskId, uintptr_t workerTaskType, std::string workerTaskLabel)
|
||||
: tid_(workerId), gid_(taskId), workerTaskType_(workerTaskType), label_(workerTaskLabel) {}
|
||||
};
|
||||
|
||||
struct TimeoutFunctionInfo {
|
||||
CoWorkerInfo coWorkerInfo_;
|
||||
WorkerInfo workerInfo_;
|
||||
int executionTime_;
|
||||
|
||||
TimeoutFunctionInfo(const CoWorkerInfo& coWorkerInfo, const WorkerInfo& workerInfo, int executionTime)
|
||||
: coWorkerInfo_(coWorkerInfo), workerInfo_(workerInfo), executionTime_(executionTime)
|
||||
{
|
||||
if (workerInfo_.workerTaskType_ != ffrt_normal_task && workerInfo_.workerTaskType_ != ffrt_queue_task) {
|
||||
workerInfo_.gid_ = UINT64_MAX; // 该task type 没有 gid
|
||||
workerInfo_.label_ = "Unsupport_Task_type"; // 该task type 没有 label
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class WorkerMonitor {
|
||||
public:
|
||||
static WorkerMonitor &GetInstance();
|
||||
void SubmitTask();
|
||||
std::string DumpTimeoutInfo();
|
||||
|
||||
private:
|
||||
WorkerMonitor();
|
||||
~WorkerMonitor();
|
||||
WorkerMonitor(const WorkerMonitor &) = delete;
|
||||
WorkerMonitor(WorkerMonitor &&) = delete;
|
||||
WorkerMonitor &operator=(const WorkerMonitor &) = delete;
|
||||
WorkerMonitor &operator=(WorkerMonitor &&) = delete;
|
||||
void SubmitSamplingTask();
|
||||
void SubmitTaskMonitor(uint64_t nextTimeoutUs);
|
||||
void SubmitMemReleaseTask();
|
||||
void CheckWorkerStatus();
|
||||
void CheckTaskStatus();
|
||||
uint64_t CalculateTaskTimeout(CPUEUTask* task, uint64_t timeoutThreshold);
|
||||
bool ControlTimeoutFreq(CPUEUTask* task);
|
||||
void RecordTimeoutTaskInfo(CPUEUTask* task);
|
||||
void RecordTimeoutFunctionInfo(const CoWorkerInfo& coWorkerInfo, CPUWorker* worker,
|
||||
TaskBase* workerTask, std::vector<TimeoutFunctionInfo>& timeoutFunctions);
|
||||
void RecordSymbolAndBacktrace(const TimeoutFunctionInfo& timeoutFunction);
|
||||
void RecordIpcInfo(const std::string& dumpInfo, int tid);
|
||||
void RecordKeyInfo(const std::string& dumpInfo);
|
||||
void ProcessWorkerInfo(std::ostringstream& oss, bool& firstQos, int qos, unsigned int cnt,
|
||||
const std::deque<pid_t>& tids);
|
||||
void RecordWorkerStatusInfo();
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::mutex submitTaskMutex_;
|
||||
bool skipSampling_ = false;
|
||||
uint64_t timeoutUs_ = 0;
|
||||
std::vector<std::pair<uint64_t, std::string>> taskTimeoutInfo_;
|
||||
WaitUntilEntry watchdogWaitEntry_;
|
||||
WaitUntilEntry tskMonitorWaitEntry_;
|
||||
WaitUntilEntry memReleaseWaitEntry_;
|
||||
std::map<CPUWorker*, TaskTimeoutInfo> workerStatus_;
|
||||
bool samplingTaskExit_ = true;
|
||||
bool taskMonitorExit_ = true;
|
||||
bool memReleaseTaskExit_ = true;
|
||||
unsigned int samplingTaskCount_ = 0;
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_C_DEADLINE_H
|
||||
#define FFRT_API_C_DEADLINE_H
|
||||
#include <stdint.h>
|
||||
#include "type_def_ext.h"
|
||||
|
||||
FFRT_C_API ffrt_interval_t ffrt_interval_create(uint64_t deadline_us, ffrt_qos_t qos);
|
||||
FFRT_C_API int ffrt_interval_update(ffrt_interval_t it, uint64_t new_deadline_us);
|
||||
FFRT_C_API int ffrt_interval_begin(ffrt_interval_t it);
|
||||
FFRT_C_API int ffrt_interval_end(ffrt_interval_t it);
|
||||
FFRT_C_API void ffrt_interval_destroy(ffrt_interval_t it);
|
||||
FFRT_C_API int ffrt_interval_join(ffrt_interval_t it);
|
||||
FFRT_C_API int ffrt_interval_leave(ffrt_interval_t it);
|
||||
#endif
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_C_EXECUTOR_TASK_H
|
||||
#define FFRT_API_C_EXECUTOR_TASK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/epoll.h>
|
||||
#include "type_def_ext.h"
|
||||
#include "c/timer.h"
|
||||
|
||||
/**
|
||||
* @brief Struct of the executor_task, also aligns with the base task class.
|
||||
*/
|
||||
typedef struct ffrt_executor_task {
|
||||
uintptr_t reserved[2];
|
||||
uintptr_t type; // 0: TaskCtx, 1~: Dynamicly Define Task, User Space Address: libuv work
|
||||
void* wq[2];
|
||||
} ffrt_executor_task_t;
|
||||
|
||||
/**
|
||||
* @brief The executor task types.
|
||||
*/
|
||||
typedef enum {
|
||||
ffrt_normal_task = 0,
|
||||
ffrt_io_task = 1,
|
||||
ffrt_uv_task, // only used to register func for libuv
|
||||
ffrt_queue_task,
|
||||
ffrt_xpu_task,
|
||||
ffrt_invalid_task,
|
||||
} ffrt_executor_task_type_t;
|
||||
|
||||
/**
|
||||
* @brief Function defined to be executed by the workers.
|
||||
*
|
||||
* @param data Indicates the args of the function defined by users.
|
||||
* @param qos Indicates the qos of the task.
|
||||
*/
|
||||
typedef void (*ffrt_executor_task_func)(ffrt_executor_task_t* data, ffrt_qos_t qos);
|
||||
|
||||
/**
|
||||
* @brief Registers a user-defined function for the workers to execute.
|
||||
*
|
||||
* @param func Indicates a user-defined function.
|
||||
* @param type Indicates which task type the function belongs to.
|
||||
*/
|
||||
FFRT_C_API void ffrt_executor_task_register_func(ffrt_executor_task_func func, ffrt_executor_task_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Submits a UV task or IO task.
|
||||
*
|
||||
* @param task Indicates a pointer to the task.
|
||||
* @param attr Indicates a pointer to the task attribute.
|
||||
*/
|
||||
FFRT_C_API void ffrt_executor_task_submit(ffrt_executor_task_t* task, const ffrt_task_attr_t* attr);
|
||||
|
||||
/**
|
||||
* @brief Cancels a UV task or IO task.
|
||||
*
|
||||
* @param task Indicates a pointer to the task.
|
||||
* @param attr Indicates the qos of the task.
|
||||
* @return Returns success or failed.
|
||||
*
|
||||
*/
|
||||
FFRT_C_API int ffrt_executor_task_cancel(ffrt_executor_task_t* task, const ffrt_qos_t qos);
|
||||
|
||||
/**
|
||||
* @brief Wakeups the ffrt poller.
|
||||
*
|
||||
* @param qos Indicates the qos of the poller.
|
||||
*/
|
||||
FFRT_C_API void ffrt_poller_wakeup(ffrt_qos_t qos);
|
||||
|
||||
/**
|
||||
* @brief Gets the number of epoll operations performed.
|
||||
*
|
||||
* @param qos Indicates the qos of the poller.
|
||||
*/
|
||||
FFRT_C_API uint8_t ffrt_epoll_get_count(ffrt_qos_t qos);
|
||||
|
||||
/**
|
||||
* @brief Querys the ffrt timer.
|
||||
*
|
||||
* @param handler Indicates the handler of the timer.
|
||||
*/
|
||||
FFRT_C_API ffrt_timer_query_t ffrt_timer_query(ffrt_qos_t qos, ffrt_timer_t handle);
|
||||
|
||||
/**
|
||||
* @brief Submits a fd event to the poller.
|
||||
*
|
||||
* FFRT provides two ways to deal with fd events:
|
||||
* - Mode 1: execute the cb function
|
||||
* - Mode 2: register fd event into FFRT by ffrt_epoll_ctl, then wait for fd event by ffrt_epoll_wait
|
||||
* In Mode 1, ffrt_epoll_ctl can be called in user thread or ffrt task
|
||||
* FFRT will monitor the fd event and then execute the cb function.
|
||||
* In Mode 2, both ffrt_epoll_ctl and ffrt_epoll_wait must be called in the same ffrt task.
|
||||
*
|
||||
* @warning Do not call `exit` in `cb` - this my cause unexpected behavior.
|
||||
*
|
||||
* @param qos Indicates the qos of the poller.
|
||||
* @param op Indicates the option of the event.
|
||||
* @param fd Indicates the fd of the event. Only supports eventfd, timerfd, and harware I/O.
|
||||
* @param events Indicates the events of the events.
|
||||
* @param data Indicates the args of the event callback function.
|
||||
* @param cb Indicates the callback function of the event.
|
||||
*/
|
||||
FFRT_C_API int ffrt_epoll_ctl(ffrt_qos_t qos, int op, int fd, uint32_t events, void* data, ffrt_poller_cb cb);
|
||||
|
||||
/**
|
||||
* @brief Waits an epoll event.
|
||||
*
|
||||
* Calling ffrt_epoll_wait will block the task.
|
||||
* Both ffrt_epoll_wait and ffrt_epoll_ctl must be called in the same ffrt task.
|
||||
*
|
||||
* @param qos Indicates the qos of the poller.
|
||||
* @param events Indicates the events of the event.
|
||||
* @param max_events Indicates the max event value.
|
||||
* @param timeout Indicates the time to timeout.
|
||||
*/
|
||||
FFRT_C_API int ffrt_epoll_wait(ffrt_qos_t qos, struct epoll_event* events, int max_events, int timeout);
|
||||
|
||||
/**
|
||||
* @brief Gets the time a task has waited in the poller.
|
||||
*
|
||||
* @param taskHandle Indicates the pointer of a task.
|
||||
*/
|
||||
FFRT_C_API uint64_t ffrt_epoll_get_wait_time(void* taskHandle);
|
||||
|
||||
/**
|
||||
* @brief Submit a coroutine IO task.
|
||||
*
|
||||
* @param co Indicates the args of a task executor function.
|
||||
* @param exec Indicates a task executor function.
|
||||
* @param destroy Indicates the destroy function of a task.
|
||||
* @param in_deps Indicates a pointer to the input dependencies.
|
||||
* @param out_deps Indicates a pointer to the output dependencies.
|
||||
* @param attr Indicates a task attribute.
|
||||
*/
|
||||
FFRT_C_API void ffrt_submit_coroutine(void* co, ffrt_coroutine_ptr_t exec, ffrt_function_t destroy,
|
||||
const ffrt_deps_t* in_deps, const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr);
|
||||
|
||||
/**
|
||||
* @brief Wakeups a coroutine IO task.
|
||||
*
|
||||
* @param task Indicates a pointer to the task.
|
||||
*/
|
||||
FFRT_C_API void ffrt_wake_coroutine(void* task);
|
||||
|
||||
/**
|
||||
* @brief Get the pointer of the current task.
|
||||
*
|
||||
* @return Returns a pointer.
|
||||
*/
|
||||
FFRT_C_API void* ffrt_get_current_task(void);
|
||||
|
||||
/**
|
||||
* @brief Obtains current coroutine stack address and size.
|
||||
*
|
||||
* @param stack_addr Coroutine stack address.
|
||||
* @param size Coroutine stack size.
|
||||
* @return Returns <b>0</b> if the stack is obtained;
|
||||
* returns <b>-1</b> otherwise.
|
||||
* @since 12
|
||||
*/
|
||||
FFRT_C_API bool ffrt_get_current_coroutine_stack(void** stack_addr, size_t* size);
|
||||
|
||||
/**
|
||||
* @brief Obtains current task.
|
||||
*
|
||||
* @param none.
|
||||
* @return Returns current task.
|
||||
* @since 12
|
||||
*/
|
||||
FFRT_C_API void* ffrt_get_cur_task(void);
|
||||
|
||||
/**
|
||||
* @brief Set the taskLocal flag in ffrt_task_attr.
|
||||
*
|
||||
* @param attr The ffrt_task_attr struct.
|
||||
* @param task_local The bool value to be set.
|
||||
* @return none.
|
||||
* @since 12
|
||||
*/
|
||||
FFRT_C_API void ffrt_task_attr_set_local(ffrt_task_attr_t* attr, bool task_local);
|
||||
|
||||
/**
|
||||
* @brief Obtains the taskLocal flag in ffrt_task_attr.
|
||||
*
|
||||
* @param attr The ffrt_task_attr struct.
|
||||
* @return The bool value of task_local.
|
||||
* @since 12
|
||||
*/
|
||||
FFRT_C_API bool ffrt_task_attr_get_local(ffrt_task_attr_t* attr);
|
||||
|
||||
/**
|
||||
* @brief Obtains the thread id of the input task handle.
|
||||
*
|
||||
* @param task_handle The task pointer.
|
||||
* @return The thread id of the input task handle.
|
||||
*/
|
||||
FFRT_C_API pthread_t ffrt_task_get_tid(void* task_handle);
|
||||
|
||||
/**
|
||||
* @brief Obtains the task id cached by the current thread.
|
||||
*
|
||||
* @return Returns the task id.
|
||||
*/
|
||||
FFRT_C_API uint64_t ffrt_get_cur_cached_task_id(void);
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_CPU_BOOST_C_API_H
|
||||
#define FFRT_CPU_BOOST_C_API_H
|
||||
#include "type_def_ext.h"
|
||||
|
||||
#define CPUBOOST_START_POINT 0
|
||||
#define CPUBOOST_MAX_CNT 32
|
||||
|
||||
FFRT_C_API int ffrt_cpu_boost_start(int ctx_id);
|
||||
|
||||
FFRT_C_API int ffrt_cpu_boost_end(int ctx_id);
|
||||
|
||||
#endif // FFRT_CPU_BOOST_C_API_H
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_C_FFRT_DUMP_H
|
||||
#define FFRT_API_C_FFRT_DUMP_H
|
||||
#include <stdint.h>
|
||||
#include "type_def_ext.h"
|
||||
|
||||
#define MAX_TASK_NAME_LENGTH (64)
|
||||
#define TASK_STAT_LENGTH (88)
|
||||
|
||||
typedef enum {
|
||||
DUMP_INFO_ALL = 0,
|
||||
DUMP_TASK_STATISTIC_INFO,
|
||||
DUMP_START_STAT,
|
||||
DUMP_STOP_STAT
|
||||
} ffrt_dump_cmd_t;
|
||||
|
||||
typedef struct ffrt_stat {
|
||||
char taskName[MAX_TASK_NAME_LENGTH];
|
||||
uint64_t funcPtr;
|
||||
uint64_t startTime;
|
||||
uint64_t endTime;
|
||||
} ffrt_stat;
|
||||
|
||||
typedef void(*ffrt_task_timeout_cb)(uint64_t gid, const char *msg, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief dump ffrt信息,包括task、queue、worker相关信息.
|
||||
*
|
||||
* @param cmd 命令类型:
|
||||
* DUMP_INFO_ALL:表示输出所有信息
|
||||
* DUMP_TASK_STATISTIC_INFO:输出任务统计信息
|
||||
* @param buf 指向需要写入的buffer
|
||||
* @param len buffer大小
|
||||
* @return 写入buffer的字符数,不包含字符串的结尾符号\0
|
||||
* 负数:表示操作未成功
|
||||
* 0 : 未写入buffer
|
||||
* 正数:成功写入buffer的字符数
|
||||
* @约束:
|
||||
* 1.buffer大小不足,ffrt记录信息不全(buffer用完则不再写入)
|
||||
* @规格:
|
||||
* 1.调用时机:业务、交互命令任意时机均可以调用
|
||||
* 2.影响:该功能执行过程中、执行过后均不影响系统、业务功能
|
||||
*/
|
||||
FFRT_C_API int ffrt_dump(ffrt_dump_cmd_t cmd, char *buf, uint32_t len);
|
||||
FFRT_C_API ffrt_task_timeout_cb ffrt_task_timeout_get_cb(void);
|
||||
FFRT_C_API void ffrt_task_timeout_set_cb(ffrt_task_timeout_cb cb);
|
||||
FFRT_C_API uint32_t ffrt_task_timeout_get_threshold(void);
|
||||
/**
|
||||
* @brief Set the ffrt task callback timeout.
|
||||
*
|
||||
* the default task callback timeout is 30 seconds,
|
||||
* The lower limit of timeout value is 1 second, if the value is less than 1 second, it will be set to 1 second,
|
||||
* The timeout value setting by this interface will take effect when the next timeout task is detected.
|
||||
*
|
||||
* @param threshold_ms ffrt task callback timeout.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API void ffrt_task_timeout_set_threshold(uint32_t threshold_ms);
|
||||
#endif /* FFRT_API_C_FFRT_DUMP_H */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_IPC_H
|
||||
#define FFRT_IPC_H
|
||||
#include "type_def_ext.h"
|
||||
|
||||
/**
|
||||
* @brief ipc set legacy mode to ffrt.
|
||||
*
|
||||
* @param mode Indicates wheather use legacy mode.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API void ffrt_this_task_set_legacy_mode(bool mode);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 FFRT_API_C_INIT_H
|
||||
#define FFRT_API_C_INIT_H
|
||||
/**
|
||||
* @brief In the subprocess, initialize the ffrt resources.
|
||||
* Only applicable for the cloning scene, and only allowed to be called once.
|
||||
*/
|
||||
FFRT_C_API void ffrt_child_init(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_INNER_API_C_QUEUE_EXT_H
|
||||
#define FFRT_INNER_API_C_QUEUE_EXT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "c/queue.h"
|
||||
|
||||
typedef enum {
|
||||
/* Allows users to submit tasks to the eventhandler through this type of queue.
|
||||
(for example, submitting tasks to the main thread and JS Worker thread) */
|
||||
ffrt_queue_eventhandler_interactive = 3,
|
||||
ffrt_queue_eventhandler_adapter = 4,
|
||||
ffrt_queue_inner_max,
|
||||
} ffrt_inner_queue_type_t;
|
||||
|
||||
typedef enum {
|
||||
/* highest priority, should be distributed until the tasks in the queue are completed */
|
||||
ffrt_inner_queue_priority_vip = 0,
|
||||
/* should be distributed at once if possible, handle time equals to send time, prior to high level */
|
||||
ffrt_inner_queue_priority_immediate,
|
||||
/* high priority, sorted by handle time, prior to low level. */
|
||||
ffrt_inner_queue_priority_high,
|
||||
/* low priority, sorted by handle time, prior to idle level. */
|
||||
ffrt_inner_queue_priority_low,
|
||||
/* lowest priority, sorted by handle time, only distribute when there is no other level inside queue. */
|
||||
ffrt_inner_queue_priority_idle,
|
||||
} ffrt_inner_queue_priority_t;
|
||||
|
||||
/**
|
||||
* @brief Checks whether a task with the given name can be found in the queue.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
* @param name Indicates name to be searched for, regular expressions are supported.
|
||||
* @return Returns whether the task is found.
|
||||
*/
|
||||
FFRT_C_API bool ffrt_queue_has_task(ffrt_queue_t queue, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Cancels all unexecuted tasks in the queue.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
*/
|
||||
FFRT_C_API void ffrt_queue_cancel_all(ffrt_queue_t queue);
|
||||
|
||||
/**
|
||||
* @brief Cancels all unexecuted tasks and wait for running tasks in the queue. No new tasks will be accepted.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
*/
|
||||
FFRT_C_API void ffrt_queue_cancel_and_wait(ffrt_queue_t queue);
|
||||
|
||||
/**
|
||||
* @brief Cancels a task with the given name in the queue.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
* @param name Indicates name of the task to be canceled, regular expressions are supported.
|
||||
* @return Returns <b>0</b> if the task is canceled;
|
||||
returns <b>1</b> otherwise.
|
||||
*/
|
||||
FFRT_C_API int ffrt_queue_cancel_by_name(ffrt_queue_t queue, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Checks whether the queue is idle.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
* @return Returns whether the queue is idle.
|
||||
*/
|
||||
FFRT_C_API bool ffrt_queue_is_idle(ffrt_queue_t queue);
|
||||
|
||||
/**
|
||||
* @brief Dumps queue information;
|
||||
including current execution, historical execution, and remaining unexecuted task information, etc.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
* @param tag Indicates tag prefix for dump information.
|
||||
* @param buf Indicates produce output, write to the character string buf.
|
||||
* @param len Indicates the size of the buffer (in bytes).
|
||||
* @param history_info Indicates whether dump history information.
|
||||
* @return Returns the number of characters printed (not including the terminating null byte '\0');
|
||||
returns -1 if an error occurred, pay special attention to returning -1 when truncation occurs.
|
||||
*/
|
||||
FFRT_C_API int ffrt_queue_dump(ffrt_queue_t queue, const char* tag, char* buf, uint32_t len, bool history_info);
|
||||
|
||||
/**
|
||||
* @brief Dumps queue task count with specified priority.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
* @param priority Indicates the execute priority of queue task.
|
||||
* @return Returns the count of tasks;
|
||||
returns -1 if an error occurred.
|
||||
*/
|
||||
FFRT_C_API int ffrt_queue_size_dump(ffrt_queue_t queue, ffrt_inner_queue_priority_t priority);
|
||||
|
||||
/**
|
||||
* @brief Binds an eventhandler object to the queue.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
* @param eventhandler Indicates an eventhandler pointer.
|
||||
*/
|
||||
FFRT_C_API void ffrt_queue_set_eventhandler(ffrt_queue_t queue, void* eventhandler);
|
||||
|
||||
/**
|
||||
* @brief Obtains the handler bound to the queue that is being executed on the current worker.
|
||||
*
|
||||
* @return Returns a non-null eventhandler pointer;
|
||||
returns a null pointer if the current task is not bound to an eventhandler.
|
||||
*/
|
||||
FFRT_C_API void* ffrt_get_current_queue_eventhandler(void);
|
||||
|
||||
/**
|
||||
* @brief Wait until all tasks in the queue are complete based on the time when this interface is invoked.
|
||||
*
|
||||
* This API is valid only for concurrent queue.
|
||||
* This interface cannot be invoked by multiple threads at the same time.
|
||||
*
|
||||
* @param queue Indicates a queue handle.
|
||||
* @return Returns 0 if waiting successful;
|
||||
returns 1 if another existing thread is invoking the interface;
|
||||
returns -1 if queue type is unsupported.
|
||||
*/
|
||||
FFRT_C_API int ffrt_concurrent_queue_wait_all(ffrt_queue_t queue);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_INNER_API_C_TASK_H
|
||||
#define FFRT_INNER_API_C_TASK_H
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "type_def_ext.h"
|
||||
|
||||
/**
|
||||
* @brief Skips a task.
|
||||
*
|
||||
* @param handle Indicates a task handle.
|
||||
* @return Returns <b>0</b> if the task is skipped;
|
||||
returns <b>-1</b> otherwise.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API int ffrt_skip(ffrt_task_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Sets cgroup attribute.
|
||||
*
|
||||
* @param qos Indicates the Qos, only support for qos_defined_ive.
|
||||
* @param attr Indicates the cgroup attribute.
|
||||
* @return Returns <b>0</b> if cgroup attribute set success;
|
||||
* returns <b>-1</b> if cgroup attribute set fail.
|
||||
*/
|
||||
FFRT_C_API int ffrt_set_cgroup_attr(ffrt_qos_t qos, ffrt_os_sched_attr* attr);
|
||||
|
||||
/**
|
||||
* @brief Restore the ffrt threads attribute to the default value for all Qos.
|
||||
*/
|
||||
FFRT_C_API void ffrt_restore_qos_config(void);
|
||||
|
||||
/**
|
||||
* @brief Sets the max num of ffrt threads in a QoS.
|
||||
*
|
||||
* @param qos Indicates the QoS.
|
||||
* @param num Indicates the max num.
|
||||
* @return Returns <b>0</b> if max num set success;
|
||||
* return <b>-1</b> if max num set fail;
|
||||
*/
|
||||
FFRT_C_API int ffrt_set_cpu_worker_max_num(ffrt_qos_t qos, uint32_t num);
|
||||
|
||||
/**
|
||||
* @brief Sets whether the task notifies worker, only support for normal task.
|
||||
*
|
||||
* @param attr Indicates a pointer to the task attribute.
|
||||
* @param notify Indicates whether the task notifies worker.
|
||||
*/
|
||||
FFRT_C_API void ffrt_task_attr_set_notify_worker(ffrt_task_attr_t* attr, bool notify);
|
||||
|
||||
/**
|
||||
* @brief Notifies a specified number of workers at a specified QoS level.
|
||||
*
|
||||
* @param qos Indicates the QoS.
|
||||
* @param number Indicates the number of workers to be notified.
|
||||
*/
|
||||
FFRT_C_API void ffrt_notify_workers(ffrt_qos_t qos, int number);
|
||||
|
||||
/**
|
||||
* @brief Obtains the ID of this queue.
|
||||
*
|
||||
* @return Returns the queue ID.
|
||||
*/
|
||||
FFRT_C_API int64_t ffrt_this_queue_get_id(void);
|
||||
|
||||
/**
|
||||
* @brief Enable the worker escape function (When all the worker threads under a QoS level fully block, the system will
|
||||
* temporarily exceed the limit on the number of worker threads and create new worker threads to execute tasks).
|
||||
* Delay penalty is added for escape function. As the number of threads increases, the thread creation delay increases.
|
||||
* Calling this function does not take effect when the escape function is enabled.
|
||||
*
|
||||
* @param one_stage_interval_ms Indicates the interval for creating threads in one-stage, default value is 10ms.
|
||||
* If input parameter value is smaller than the default value, the setting fails.
|
||||
* @param two_stage_interval_ms Indicates the interval for creating threads in two-stage, default value is 100ms.
|
||||
* If input parameter value is smaller than the default value, the setting fails.
|
||||
* @param three_stage_interval_ms Indicates the interval for creating threads in three-stage, default value is 1000ms.
|
||||
* If input parameter value is smaller than the default value, the setting fails.
|
||||
* @param one_stage_worker_num Indicates the number of workers in one-stage.
|
||||
* @param two_stage_worker_num Indicates the number of workers in two-stage.
|
||||
* @return Returns 0 if the parameters are valid and the escape function is enabled successfully;
|
||||
* returns 1 otherwise.
|
||||
*/
|
||||
FFRT_C_API int ffrt_enable_worker_escape(uint64_t one_stage_interval_ms, uint64_t two_stage_interval_ms,
|
||||
uint64_t three_stage_interval_ms, uint64_t one_stage_worker_num, uint64_t two_stage_worker_num);
|
||||
|
||||
/**
|
||||
* @brief Disable the worker escape function (When all the worker threads under a QoS level fully block, the system will
|
||||
* temporarily exceed the limit on the number of worker threads and create new worker threads to execute tasks).
|
||||
*/
|
||||
FFRT_C_API void ffrt_disable_worker_escape(void);
|
||||
|
||||
/**
|
||||
* @brief Set the sched mode of the QoS.
|
||||
*/
|
||||
FFRT_C_API void ffrt_set_sched_mode(ffrt_qos_t qos, ffrt_sched_mode mode);
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_C_THREAD_H
|
||||
#define FFRT_API_C_THREAD_H
|
||||
#include "type_def_ext.h"
|
||||
|
||||
FFRT_C_API int ffrt_thread_create(ffrt_thread_t* thr, const ffrt_thread_attr_t* attr, void*(*func)(void*), void* arg);
|
||||
FFRT_C_API int ffrt_thread_join(ffrt_thread_t thr, void** res);
|
||||
FFRT_C_API int ffrt_thread_detach(ffrt_thread_t thr);
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file type_def.h
|
||||
*
|
||||
* @brief Declares common types.
|
||||
*
|
||||
* @since 10
|
||||
*/
|
||||
#ifndef FFRT_INNER_API_C_TYPE_DEF_H
|
||||
#define FFRT_INNER_API_C_TYPE_DEF_H
|
||||
#include <stdint.h>
|
||||
#include "c/type_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define FFRT_C_API extern "C"
|
||||
#else
|
||||
#define FFRT_C_API
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enumerates the task QoS types.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ffrt_qos_deadline_request = 4,
|
||||
ffrt_qos_user_interactive,
|
||||
ffrt_qos_max = ffrt_qos_user_interactive,
|
||||
} ffrt_inner_qos_default_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_stack_protect_weak,
|
||||
ffrt_stack_protect_strong
|
||||
} ffrt_stack_protect_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_thread_attr_storage_size = 64,
|
||||
} ffrt_inner_storage_size_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t storage[(ffrt_thread_attr_storage_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
|
||||
} ffrt_thread_attr_t;
|
||||
|
||||
#define MAX_CPUMAP_LENGTH 100 // this is in c and code style
|
||||
typedef struct {
|
||||
int shares;
|
||||
int latency_nice;
|
||||
int uclamp_min;
|
||||
int uclamp_max;
|
||||
int vip_prio;
|
||||
char cpumap[MAX_CPUMAP_LENGTH];
|
||||
} ffrt_os_sched_attr;
|
||||
|
||||
typedef void* ffrt_thread_t;
|
||||
|
||||
typedef void* ffrt_interval_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_sys_event_type_read,
|
||||
} ffrt_sys_event_type_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_sys_event_status_no_timeout,
|
||||
ffrt_sys_event_status_timeout
|
||||
} ffrt_sys_event_status_t;
|
||||
|
||||
typedef void* ffrt_sys_event_handle_t;
|
||||
|
||||
typedef void* ffrt_config_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_coroutine_stackless,
|
||||
ffrt_coroutine_with_stack,
|
||||
} ffrt_coroutine_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_coroutine_pending = 0,
|
||||
ffrt_coroutine_ready = 1,
|
||||
} ffrt_coroutine_ret_t;
|
||||
|
||||
typedef ffrt_coroutine_ret_t(*ffrt_coroutine_ptr_t)(void*);
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
void* data;
|
||||
void(*cb)(void*, uint32_t);
|
||||
} ffrt_poller_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_timer_notfound = -1,
|
||||
ffrt_timer_not_executed = 0,
|
||||
ffrt_timer_executed = 1,
|
||||
} ffrt_timer_query_t;
|
||||
|
||||
typedef enum {
|
||||
ffrt_sched_default_mode = 0,
|
||||
ffrt_sched_performance_mode,
|
||||
ffrt_sched_energy_saving_mode,
|
||||
} ffrt_sched_mode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace ffrt {
|
||||
enum qos_inner_default {
|
||||
qos_deadline_request = ffrt_qos_deadline_request,
|
||||
qos_user_interactive = ffrt_qos_user_interactive,
|
||||
qos_max = ffrt_qos_max,
|
||||
};
|
||||
|
||||
enum class stack_protect {
|
||||
weak = ffrt_stack_protect_weak,
|
||||
strong = ffrt_stack_protect_strong,
|
||||
};
|
||||
|
||||
enum class sched_mode_type : uint8_t {
|
||||
sched_default_mode = ffrt_sched_default_mode,
|
||||
sched_performance_mode = ffrt_sched_performance_mode,
|
||||
sched_energy_saving_mode = ffrt_sched_energy_saving_mode,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_CPP_DEADLINE_H
|
||||
#define FFRT_API_CPP_DEADLINE_H
|
||||
#include <stdint.h>
|
||||
#include "c/deadline.h"
|
||||
|
||||
namespace ffrt {
|
||||
using interval = ffrt_interval_t;
|
||||
|
||||
/**
|
||||
* @brief app create an anonymous interval, the number is limited. should specify the deadline
|
||||
*/
|
||||
static inline interval qos_interval_create(uint64_t deadline_us, qos qos_ = static_cast<int>(qos_deadline_request))
|
||||
{
|
||||
return ffrt_interval_create(deadline_us, qos_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief destroy a interval
|
||||
*/
|
||||
static inline void qos_interval_destroy(interval it)
|
||||
{
|
||||
ffrt_interval_destroy(it);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief start the interval
|
||||
*/
|
||||
static inline int qos_interval_begin(interval it)
|
||||
{
|
||||
return ffrt_interval_begin(it);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief update interval
|
||||
*/
|
||||
static inline int qos_interval_update(interval it, uint64_t new_deadline_us)
|
||||
{
|
||||
return ffrt_interval_update(it, new_deadline_us);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief interval become inactive until next begin
|
||||
*/
|
||||
static inline int qos_interval_end(interval it)
|
||||
{
|
||||
return ffrt_interval_end(it);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief current task or thread join an interval, only allow FIXED number of threads to join a interval
|
||||
*/
|
||||
static inline int qos_interval_join(interval it)
|
||||
{
|
||||
return ffrt_interval_join(it);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief current task or thread leave an interval
|
||||
*/
|
||||
static inline int qos_interval_leave(interval it)
|
||||
{
|
||||
return ffrt_interval_leave(it);
|
||||
}
|
||||
}; // namespace ffrt
|
||||
|
||||
#endif
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_CPP_FUTURE_H
|
||||
#define FFRT_API_CPP_FUTURE_H
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
#include "cpp/condition_variable.h"
|
||||
#include "thread.h"
|
||||
|
||||
namespace ffrt {
|
||||
struct non_copyable {
|
||||
protected:
|
||||
non_copyable() = default;
|
||||
~non_copyable() = default;
|
||||
non_copyable(const non_copyable&) = delete;
|
||||
non_copyable& operator=(const non_copyable&) = delete;
|
||||
};
|
||||
enum class future_status { ready, timeout, deferred };
|
||||
|
||||
namespace detail {
|
||||
template <typename Derived>
|
||||
struct shared_state_base : private non_copyable {
|
||||
void wait() const noexcept
|
||||
{
|
||||
std::unique_lock lk(this->m_mtx);
|
||||
wait_(lk);
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
future_status wait_for(const std::chrono::duration<Rep, Period>& waitTime) const noexcept
|
||||
{
|
||||
std::unique_lock<mutex> lk(m_mtx);
|
||||
return m_cv.wait_for(lk, waitTime, [this] { return get_derived().has_value(); }) ? future_status::ready :
|
||||
future_status::timeout;
|
||||
}
|
||||
|
||||
template <typename Clock, typename Duration>
|
||||
future_status wait_until(const std::chrono::time_point<Clock, Duration>& tp) const noexcept
|
||||
{
|
||||
std::unique_lock<mutex> lk(m_mtx);
|
||||
return m_cv.wait_until(lk, tp, [this] { return get_derived().has_value(); }) ? future_status::ready :
|
||||
future_status::timeout;
|
||||
}
|
||||
|
||||
protected:
|
||||
void wait_(std::unique_lock<mutex>& lk) const noexcept
|
||||
{
|
||||
m_cv.wait(lk, [this] { return get_derived().has_value(); });
|
||||
}
|
||||
|
||||
mutable mutex m_mtx;
|
||||
mutable condition_variable m_cv;
|
||||
|
||||
private:
|
||||
const Derived& get_derived() const
|
||||
{
|
||||
return *static_cast<const Derived*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct shared_state : public shared_state_base<shared_state<R>> {
|
||||
void set_value(const R& value) noexcept
|
||||
{
|
||||
std::unique_lock<mutex> lk(this->m_mtx);
|
||||
m_res.emplace(value);
|
||||
this->m_cv.notify_all();
|
||||
}
|
||||
|
||||
void set_value(R&& value) noexcept
|
||||
{
|
||||
std::unique_lock<mutex> lk(this->m_mtx);
|
||||
m_res.emplace(std::move(value));
|
||||
this->m_cv.notify_all();
|
||||
}
|
||||
|
||||
R& get() noexcept
|
||||
{
|
||||
std::unique_lock lk(this->m_mtx);
|
||||
this->wait_(lk);
|
||||
return m_res.value();
|
||||
}
|
||||
|
||||
bool has_value() const noexcept
|
||||
{
|
||||
return m_res.has_value();
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<R> m_res;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shared_state<void> : public shared_state_base<shared_state<void>> {
|
||||
void set_value() noexcept
|
||||
{
|
||||
std::unique_lock<mutex> lk(this->m_mtx);
|
||||
m_hasValue = true;
|
||||
this->m_cv.notify_all();
|
||||
}
|
||||
|
||||
void get() noexcept
|
||||
{
|
||||
std::unique_lock lk(this->m_mtx);
|
||||
this->wait_(lk);
|
||||
}
|
||||
|
||||
bool has_value() const noexcept
|
||||
{
|
||||
return m_hasValue;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_hasValue {false};
|
||||
};
|
||||
}; // namespace detail
|
||||
|
||||
template <typename R>
|
||||
class future : private non_copyable {
|
||||
template <typename>
|
||||
friend struct promise;
|
||||
|
||||
template <typename>
|
||||
friend struct packaged_task;
|
||||
|
||||
public:
|
||||
explicit future(const std::shared_ptr<detail::shared_state<R>>& state) noexcept : m_state(state)
|
||||
{
|
||||
}
|
||||
|
||||
future() noexcept = default;
|
||||
|
||||
future(future&& fut) noexcept
|
||||
{
|
||||
swap(fut);
|
||||
}
|
||||
future& operator=(future&& fut) noexcept
|
||||
{
|
||||
if (this != &fut) {
|
||||
future tmp(std::move(fut));
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool valid() const noexcept
|
||||
{
|
||||
return m_state != nullptr;
|
||||
}
|
||||
|
||||
R get() noexcept
|
||||
{
|
||||
auto tmp = std::move(m_state);
|
||||
if constexpr(!std::is_void_v<R>) {
|
||||
return std::move(tmp->get());
|
||||
} else {
|
||||
return tmp->get();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
future_status wait_for(const std::chrono::duration<Rep, Period>& waitTime) const noexcept
|
||||
{
|
||||
return m_state->wait_for(waitTime);
|
||||
}
|
||||
|
||||
template <typename Clock, typename Duration>
|
||||
future_status wait_until(const std::chrono::time_point<Clock, Duration>& tp) const noexcept
|
||||
{
|
||||
return m_state->wait_until(tp);
|
||||
}
|
||||
|
||||
void wait() const noexcept
|
||||
{
|
||||
m_state->wait();
|
||||
}
|
||||
|
||||
void swap(future<R>& rhs) noexcept
|
||||
{
|
||||
std::swap(m_state, rhs.m_state);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<detail::shared_state<R>> m_state;
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct promise : private non_copyable {
|
||||
promise() noexcept : m_state {std::make_shared<detail::shared_state<R>>()}
|
||||
{
|
||||
}
|
||||
promise(promise&& p) noexcept
|
||||
{
|
||||
swap(p);
|
||||
}
|
||||
promise& operator=(promise&& p) noexcept
|
||||
{
|
||||
if (this != &p) {
|
||||
promise tmp(std::move(p));
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set_value(const R& value) noexcept
|
||||
{
|
||||
m_state->set_value(value);
|
||||
}
|
||||
|
||||
void set_value(R&& value) noexcept
|
||||
{
|
||||
m_state->set_value(std::move(value));
|
||||
}
|
||||
|
||||
future<R> get_future() noexcept
|
||||
{
|
||||
return future<R> {m_state};
|
||||
}
|
||||
|
||||
void swap(promise<R>& rhs) noexcept
|
||||
{
|
||||
std::swap(m_state, rhs.m_state);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<detail::shared_state<R>> m_state;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct promise<void> : private non_copyable {
|
||||
promise() noexcept : m_state {std::make_shared<detail::shared_state<void>>()}
|
||||
{
|
||||
}
|
||||
promise(promise&& p) noexcept
|
||||
{
|
||||
swap(p);
|
||||
}
|
||||
promise& operator=(promise&& p) noexcept
|
||||
{
|
||||
if (this != &p) {
|
||||
promise tmp(std::move(p));
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set_value() noexcept
|
||||
{
|
||||
m_state->set_value();
|
||||
}
|
||||
|
||||
future<void> get_future() noexcept
|
||||
{
|
||||
return future<void> {m_state};
|
||||
}
|
||||
|
||||
void swap(promise<void>& rhs) noexcept
|
||||
{
|
||||
std::swap(m_state, rhs.m_state);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<detail::shared_state<void>> m_state;
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct packaged_task;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct packaged_task<R(Args...)> {
|
||||
packaged_task() noexcept = default;
|
||||
|
||||
packaged_task(const packaged_task& pt) noexcept
|
||||
{
|
||||
m_fn = pt.m_fn;
|
||||
m_state = pt.m_state;
|
||||
}
|
||||
|
||||
packaged_task(packaged_task&& pt) noexcept
|
||||
{
|
||||
swap(pt);
|
||||
}
|
||||
|
||||
packaged_task& operator=(packaged_task&& pt) noexcept
|
||||
{
|
||||
if (this != &pt) {
|
||||
packaged_task tmp(std::move(pt));
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
explicit packaged_task(F&& f) noexcept
|
||||
: m_fn {std::forward<F>(f)}, m_state {std::make_shared<detail::shared_state<R>>()}
|
||||
{
|
||||
}
|
||||
|
||||
bool valid() const noexcept
|
||||
{
|
||||
return bool(m_fn) && m_state != nullptr;
|
||||
}
|
||||
|
||||
future<R> get_future() noexcept
|
||||
{
|
||||
return future<R> {m_state};
|
||||
}
|
||||
|
||||
void operator()(Args... args)
|
||||
{
|
||||
if constexpr(!std::is_void_v<R>) {
|
||||
m_state->set_value(m_fn(std::forward<Args>(args)...));
|
||||
} else {
|
||||
m_fn(std::forward<Args>(args)...);
|
||||
m_state->set_value();
|
||||
}
|
||||
}
|
||||
|
||||
void swap(packaged_task& pt) noexcept
|
||||
{
|
||||
std::swap(m_fn, pt.m_fn);
|
||||
std::swap(m_state, pt.m_state);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<R(Args...)> m_fn;
|
||||
std::shared_ptr<detail::shared_state<R>> m_state;
|
||||
};
|
||||
|
||||
template <typename F, typename... Args>
|
||||
future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>> async(F&& f, Args&& ... args)
|
||||
{
|
||||
using R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
|
||||
packaged_task<R(std::decay_t<Args>...)> pt {std::forward<F>(f)};
|
||||
auto fut {pt.get_future()};
|
||||
auto th = ffrt::thread(std::move(pt), std::forward<Args>(args)...);
|
||||
th.detach();
|
||||
return fut;
|
||||
}
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_CPP_QOS_CONVERT_H
|
||||
#define FFRT_API_CPP_QOS_CONVERT_H
|
||||
#include "c/type_def.h"
|
||||
|
||||
namespace ffrt {
|
||||
/**
|
||||
* @brief get current thread static qos level
|
||||
*/
|
||||
int GetStaticQos(qos &static_qos);
|
||||
|
||||
/**
|
||||
* @brief get current thread dynamic qos level
|
||||
*/
|
||||
int GetDynamicQos(qos &dynamic_qos);
|
||||
}; // namespace ffrt
|
||||
|
||||
#endif // FFRT_API_CPP_QOS_CONVERT_H
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file task.h
|
||||
*
|
||||
* @brief Declares the task inner interfaces in C++.
|
||||
*
|
||||
* @since 10
|
||||
*/
|
||||
#ifndef FFRT_INNER_API_CPP_TASK_H
|
||||
#define FFRT_INNER_API_CPP_TASK_H
|
||||
#include <cstdint>
|
||||
#include "c/task_ext.h"
|
||||
#include "cpp/task.h"
|
||||
|
||||
namespace ffrt {
|
||||
/**
|
||||
* @brief Skips a task.
|
||||
*
|
||||
* @param handle Indicates a task handle.
|
||||
* @return Returns <b>0</b> if the task is skipped;
|
||||
returns <b>-1</b> otherwise.
|
||||
* @since 10
|
||||
*/
|
||||
static inline int skip(task_handle &handle)
|
||||
{
|
||||
return ffrt_skip(handle);
|
||||
}
|
||||
|
||||
void sync_io(int fd);
|
||||
|
||||
void set_trace_tag(const char* name);
|
||||
|
||||
void clear_trace_tag();
|
||||
|
||||
static inline int set_cgroup_attr(qos qos_, ffrt_os_sched_attr *attr)
|
||||
{
|
||||
return ffrt_set_cgroup_attr(qos_, attr);
|
||||
}
|
||||
|
||||
static inline void restore_qos_config()
|
||||
{
|
||||
ffrt_restore_qos_config();
|
||||
}
|
||||
|
||||
static inline int set_cpu_worker_max_num(qos qos_, uint32_t num)
|
||||
{
|
||||
return ffrt_set_cpu_worker_max_num(qos_, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notifies a specified number of workers at a specified QoS level.
|
||||
*
|
||||
* @param qos_ Indicates the QoS.
|
||||
* @param number Indicates the number of workers to be notified.
|
||||
*/
|
||||
static inline void notify_workers(qos qos_, int number)
|
||||
{
|
||||
return ffrt_notify_workers(qos_, number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Obtains the ID of this queue.
|
||||
*
|
||||
* @return Returns the queue ID.
|
||||
*/
|
||||
static inline int64_t get_queue_id()
|
||||
{
|
||||
return ffrt_this_queue_get_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the worker escape function (When all the worker threads under a QoS level fully block, the system will
|
||||
* temporarily exceed the limit on the number of worker threads and create new worker threads to execute tasks).
|
||||
* Delay penalty is added for escape function. As the number of threads increases, the thread creation delay increases.
|
||||
* Calling this function does not take effect when the escape function is enabled.
|
||||
*
|
||||
* @param one_stage_interval_ms Indicates the interval for creating threads in one-stage, default value is 10ms.
|
||||
* If input parameter value is smaller than the default value, the setting fails.
|
||||
* @param two_stage_interval_ms Indicates the interval for creating threads in two-stage, default value is 100ms.
|
||||
* If input parameter value is smaller than the default value, the setting fails.
|
||||
* @param three_stage_interval_ms Indicates the interval for creating threads in three-stage, default value is 1000ms.
|
||||
* If input parameter value is smaller than the default value, the setting fails.
|
||||
* @param one_stage_worker_num Indicates the number of workers in one-stage.
|
||||
* @param two_stage_worker_num Indicates the number of workers in two-stage.
|
||||
* @return Returns 0 if the parameters are valid and the escape function is enabled successfully;
|
||||
* returns 1 otherwise.
|
||||
*/
|
||||
static inline int enable_worker_escape(uint64_t one_stage_interval_ms = 10, uint64_t two_stage_interval_ms = 100,
|
||||
uint64_t three_stage_interval_ms = 1000, uint64_t one_stage_worker_num = 128, uint64_t two_stage_worker_num = 256)
|
||||
{
|
||||
return ffrt_enable_worker_escape(one_stage_interval_ms, two_stage_interval_ms,
|
||||
three_stage_interval_ms, one_stage_worker_num, two_stage_worker_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the worker escape function (When all the worker threads under a QoS level fully block, the system will
|
||||
* temporarily exceed the limit on the number of worker threads and create new worker threads to execute tasks).
|
||||
*
|
||||
*/
|
||||
static inline void disable_worker_escape()
|
||||
{
|
||||
ffrt_disable_worker_escape();
|
||||
}
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_CPP_THREAD_H
|
||||
#define FFRT_API_CPP_THREAD_H
|
||||
#include <memory>
|
||||
#include "cpp/task.h"
|
||||
|
||||
namespace ffrt {
|
||||
class thread {
|
||||
public:
|
||||
thread() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Fn, typename... Args,
|
||||
class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, thread>>>
|
||||
explicit thread(const char* name, qos qos_, Fn&& fn, Args&&... args)
|
||||
{
|
||||
is_joinable = std::make_unique<task_handle>();
|
||||
using Target = std::tuple<std::decay_t<Fn>, std::decay_t<Args>...>;
|
||||
auto tup = new Target(std::forward<Fn>(fn), std::forward<Args>(args)...);
|
||||
*is_joinable = ffrt::submit_h([tup]() {
|
||||
execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>());
|
||||
delete tup;
|
||||
}, {}, {}, ffrt::task_attr().name(name).qos(qos_));
|
||||
}
|
||||
|
||||
template <typename Fn, typename... Args,
|
||||
class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, thread>>>
|
||||
explicit thread(qos qos_, Fn&& fn, Args&&... args)
|
||||
{
|
||||
is_joinable = std::make_unique<task_handle>();
|
||||
using Target = std::tuple<std::decay_t<Fn>, std::decay_t<Args>...>;
|
||||
auto tup = new Target(std::forward<Fn>(fn), std::forward<Args>(args)...);
|
||||
*is_joinable = ffrt::submit_h([tup]() {
|
||||
execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>());
|
||||
delete tup;
|
||||
}, {}, {}, ffrt::task_attr().qos(qos_));
|
||||
}
|
||||
|
||||
template <class Fn, class... Args,
|
||||
class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, thread>>,
|
||||
class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, char*>>,
|
||||
class = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, qos>>>
|
||||
explicit thread(Fn&& fn, Args&& ... args)
|
||||
{
|
||||
is_joinable = std::make_unique<task_handle>();
|
||||
using Target = std::tuple<std::decay_t<Fn>, std::decay_t<Args>...>;
|
||||
auto tup = new Target (std::forward<Fn>(fn), std::forward<Args>(args)...);
|
||||
*is_joinable = ffrt::submit_h([tup]() {
|
||||
execute(*tup, std::make_index_sequence<std::tuple_size_v<Target>>());
|
||||
delete tup;
|
||||
});
|
||||
}
|
||||
|
||||
thread(const thread&) = delete;
|
||||
thread& operator=(const thread&) = delete;
|
||||
|
||||
thread(thread&& th) noexcept
|
||||
{
|
||||
swap(th);
|
||||
}
|
||||
|
||||
thread& operator=(thread&& th) noexcept
|
||||
{
|
||||
if (this != &th) {
|
||||
thread tmp(std::move(th));
|
||||
swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool joinable() const noexcept
|
||||
{
|
||||
return is_joinable.get() && *is_joinable;
|
||||
}
|
||||
|
||||
void detach() noexcept
|
||||
{
|
||||
is_joinable = nullptr;
|
||||
}
|
||||
|
||||
void join() noexcept
|
||||
{
|
||||
if (joinable()) {
|
||||
ffrt::wait({*is_joinable});
|
||||
is_joinable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~thread()
|
||||
{
|
||||
if (joinable()) {
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<class Target, size_t... Idxs>
|
||||
static inline void execute(Target& tup,
|
||||
std::index_sequence<Idxs...>)
|
||||
{
|
||||
std::invoke(std::move(std::get<Idxs>(tup))...);
|
||||
}
|
||||
|
||||
void swap(thread& other) noexcept
|
||||
{
|
||||
is_joinable.swap(other.is_joinable);
|
||||
};
|
||||
std::unique_ptr<task_handle> is_joinable;
|
||||
};
|
||||
} // namespace ffrt
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 FFRT_API_FFRT_INNER_H
|
||||
#define FFRT_API_FFRT_INNER_H
|
||||
#include "ffrt.h"
|
||||
#ifdef __cplusplus
|
||||
#include "c/ffrt_dump.h"
|
||||
#include "c/queue_ext.h"
|
||||
#include "cpp/thread.h"
|
||||
#include "cpp/future.h"
|
||||
#include "cpp/task_ext.h"
|
||||
#include "cpp/deadline.h"
|
||||
#include "cpp/qos_convert.h"
|
||||
#else
|
||||
#include "c/task_ext.h"
|
||||
#include "c/queue_ext.h"
|
||||
#include "c/thread.h"
|
||||
#include "c/executor_task.h"
|
||||
#include "c/ffrt_dump.h"
|
||||
#include "c/deadline.h"
|
||||
#include "c/ffrt_cpu_boost.h"
|
||||
#include "c/ffrt_ipc.h"
|
||||
#include "c/init.h"
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup FFRT
|
||||
* @{
|
||||
*
|
||||
* @brief Provides FFRT C APIs.
|
||||
*
|
||||
* @since 10
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file condition_variable.h
|
||||
*
|
||||
* @brief Declares the condition variable interfaces in C.
|
||||
*
|
||||
* @library libffrt.z.so
|
||||
* @kit FunctionFlowRuntimeKit
|
||||
* @syscap SystemCapability.Resourceschedule.Ffrt.Core
|
||||
* @since 10
|
||||
*/
|
||||
|
||||
#ifndef FFRT_API_C_CONDITION_VARIABLE_H
|
||||
#define FFRT_API_C_CONDITION_VARIABLE_H
|
||||
|
||||
#include <time.h>
|
||||
#include "type_def.h"
|
||||
|
||||
/**
|
||||
* @brief Initializes a condition variable.
|
||||
*
|
||||
* @param cond Indicates a pointer to the condition variable.
|
||||
* @param attr Indicates a pointer to the condition variable attribute.
|
||||
* @return Returns <b>ffrt_success</b> if the condition variable is initialized;
|
||||
returns <b>ffrt_error_inval</b> otherwise.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API int ffrt_cond_init(ffrt_cond_t* cond, const ffrt_condattr_t* attr);
|
||||
|
||||
/**
|
||||
* @brief Unblocks at least one of the threads that are blocked on a condition variable.
|
||||
*
|
||||
* @param cond Indicates a pointer to the condition variable.
|
||||
* @return Returns <b>ffrt_success</b> if the thread is unblocked;
|
||||
returns <b>ffrt_error_inval</b> otherwise.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API int ffrt_cond_signal(ffrt_cond_t* cond);
|
||||
|
||||
/**
|
||||
* @brief Unblocks all threads currently blocked on a condition variable.
|
||||
*
|
||||
* @param cond Indicates a pointer to the condition variable.
|
||||
* @return Returns <b>ffrt_success</b> if the threads are unblocked;
|
||||
returns <b>ffrt_error_inval</b> otherwise.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API int ffrt_cond_broadcast(ffrt_cond_t* cond);
|
||||
|
||||
/**
|
||||
* @brief Blocks the calling thread.
|
||||
*
|
||||
* @param cond Indicates a pointer to the condition variable.
|
||||
* @param mutex Indicates a pointer to the mutex.
|
||||
* @return Returns <b>ffrt_success</b> if the thread is unblocked after being blocked;
|
||||
returns <b>ffrt_error_inval</b> otherwise.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API int ffrt_cond_wait(ffrt_cond_t* cond, ffrt_mutex_t* mutex);
|
||||
|
||||
/**
|
||||
* @brief Blocks the calling thread for a given duration.
|
||||
*
|
||||
* If <b>ffrt_cond_signal</b> or <b>ffrt_cond_broadcast</b> is not called to unblock the thread
|
||||
* when the maximum duration reaches, the thread is automatically unblocked.
|
||||
*
|
||||
* @param cond Indicates a pointer to the condition variable.
|
||||
* @param mutex Indicates a pointer to the mutex.
|
||||
* @param time_point Indicates the maximum duration that the thread is blocked.
|
||||
* @return Returns <b>ffrt_success</b> if the thread is unblocked after being blocked;
|
||||
returns <b>ffrt_error_timedout</b> if the maximum duration reaches;
|
||||
returns <b>ffrt_error_inval</b> if the blocking fails.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API int ffrt_cond_timedwait(ffrt_cond_t* cond, ffrt_mutex_t* mutex, const struct timespec* time_point);
|
||||
|
||||
/**
|
||||
* @brief Destroys a condition variable, the user needs to invoke this interface.
|
||||
*
|
||||
* @param cond Indicates a pointer to the condition variable.
|
||||
* @return Returns <b>ffrt_success</b> if the condition variable is destroyed;
|
||||
returns <b>ffrt_error_inval</b> otherwise.
|
||||
* @since 10
|
||||
*/
|
||||
FFRT_C_API int ffrt_cond_destroy(ffrt_cond_t* cond);
|
||||
|
||||
#endif // FFRT_API_C_CONDITION_VARIABLE_H
|
||||
/** @} */
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup FFRT
|
||||
* @{
|
||||
*
|
||||
* @brief Provides FFRT C APIs.
|
||||
*
|
||||
* @since 20
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file fiber.h
|
||||
*
|
||||
* @brief Declares the fiber interfaces in C.
|
||||
*
|
||||
* @library libffrt.z.so
|
||||
* @kit FunctionFlowRuntimeKit
|
||||
* @syscap SystemCapability.Resourceschedule.Ffrt.Core
|
||||
* @since 20
|
||||
*/
|
||||
|
||||
#ifndef FFRT_API_C_FIBER_H
|
||||
#define FFRT_API_C_FIBER_H
|
||||
|
||||
#include "type_def.h"
|
||||
|
||||
/**
|
||||
* @brief Initializes a fiber.
|
||||
*
|
||||
* This function initializes a fiber structure, preparing it for execution.
|
||||
*
|
||||
* @param fiber Indicates the pointer to the fiber structure to be initialized.
|
||||
* @param func Indicates the entry point function that the fiber will execute.
|
||||
* @param arg Indicates the argument to be passed to the entry point function.
|
||||
* @param stack Indicates the pointer to the memory region to be used as the fiber's stack.
|
||||
* @param stack_size Indicates the size of the stack in bytes.
|
||||
* @return Returns <b>ffrt_success</b> if the fiber is initialized;
|
||||
returns <b>ffrt_error</b> otherwise.
|
||||
* @since 20
|
||||
*/
|
||||
FFRT_C_API int ffrt_fiber_init(ffrt_fiber_t* fiber, void(*func)(void*), void* arg, void* stack, size_t stack_size);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Switch execution context between two fibers.
|
||||
*
|
||||
* Switches the execution context by saving the current context into the fiber specified
|
||||
* by @c from and restoring the context from the fiber specified by @c to.
|
||||
*
|
||||
* @param from Indicates the pointer to the fiber into which the current context will be saved.
|
||||
* @param to Indicates the pointer to the fiber from which the context will be restored.
|
||||
* @since 20
|
||||
*/
|
||||
FFRT_C_API void ffrt_fiber_switch(ffrt_fiber_t* from, ffrt_fiber_t* to);
|
||||
|
||||
#endif // FFRT_API_C_FIBER_H
|
||||
/** @} */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue