Compare commits

...

7 Commits

Author SHA1 Message Date
jxt1234 3c7914676c
Merge 3db5a478ed into fa3b2161a9 2025-10-06 22:44:57 +05:45
jxt1234 fa3b2161a9
Merge pull request #3929 from alibaba/feature/bugfix
android / android_build (push) Has been cancelled Details
ios / ios_build (push) Has been cancelled Details
linux / linux_buil_test (push) Has been cancelled Details
macos / macos_buil_test (push) Has been cancelled Details
windows / windows_build_test (push) Has been cancelled Details
MNN:Bugfix: Fix bug for https://github.com/alibaba/MNN/issues/3924
2025-10-05 15:02:35 +08:00
xiaying 2a750ad7f8 MNN:Bugfix: Fix bug for https://github.com/alibaba/MNN/issues/3924 2025-10-05 14:35:21 +08:00
jxt1234 ad83430bf8
Merge pull request #3918 from Edward-Elric233/fix/windows-install-dll
Fix: install Windows DLLs to bin directory
2025-10-05 14:34:21 +08:00
cloud.wang 0f1376f015 Fix: install Windows DLLs to bin directory
Currently, when building shared libraries on Windows with MSVC or MinGW,
`cmake --install` does not copy the generated `.dll` files because the
`install(TARGETS ...)` command does not specify a `RUNTIME DESTINATION`.
In CMake, `.dll` files are classified as RUNTIME type, and they need an
explicit `RUNTIME DESTINATION` to be installed.

This patch updates the install() rule to:

install(TARGETS MNN
	RUNTIME DESTINATION bin
	LIBRARY DESTINATION lib
	ARCHIVE DESTINATION lib
)

- On Windows:
	* `.dll` → bin/
	* `.lib` (import/static library) → lib/
- On Linux/macOS:
	* `.so` / `.dylib` → lib/ (unchanged)
	* No impact on current behavior

This follows CMake's cross-platform installation conventions, and makes
`cmake --install` produce a standard and complete installation layout.
2025-09-29 22:03:21 +08:00
xiaying 3db5a478ed MNN:FFRT: Fix bug for so increase 2025-08-30 14:36:11 +08:00
xiaying c0bd7bac72 MNN:Feature: Add FFRT 2025-08-28 17:10:58 +08:00
301 changed files with 46400 additions and 6 deletions

14
3rd_party/ffrt/.autocorrectignore vendored Normal file
View File

@ -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/

73
3rd_party/ffrt/.autocorrectrc vendored Normal file
View File

@ -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

15
3rd_party/ffrt/.clang-format vendored Normal file
View File

@ -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
---

8
3rd_party/ffrt/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
#ignore files
.vscode
ffrt.cfg
build
test/build
benchmarks/output
output
trace.json

6
3rd_party/ffrt/.markdownlint.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"MD013": false,
"MD024": {
"siblings_only": true
}
}

19
3rd_party/ffrt/BENCHMARKS.md vendored Normal file
View File

@ -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. 测试结果已取平均

266
3rd_party/ffrt/BUILD.gn vendored Normal file
View File

@ -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",
]
}

108
3rd_party/ffrt/BUILD.md vendored Normal file
View File

@ -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依次为 ERRORWARNINFODEBUG例如需要打开 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",
]
```

114
3rd_party/ffrt/CMakeLists.txt vendored Normal file
View File

@ -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()

69
3rd_party/ffrt/CONTRIBUTING.md vendored Normal file
View File

@ -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!

201
3rd_party/ffrt/LICENSE vendored Normal file
View File

@ -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.

32
3rd_party/ffrt/OAT.xml vendored Normal file
View File

@ -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>

69
3rd_party/ffrt/README.md vendored Normal file
View File

@ -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.

6
3rd_party/ffrt/RELEASE.md vendored Normal file
View File

@ -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.

71
3rd_party/ffrt/TESTING.md vendored Normal file
View File

@ -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
```

94
3rd_party/ffrt/bundle.json vendored Normal file
View File

@ -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"
]
}
}
}

25
3rd_party/ffrt/cspell.json vendored Normal file
View File

@ -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"
]
}

19
3rd_party/ffrt/ffrt.gni vendored Normal file
View File

@ -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"
}

49
3rd_party/ffrt/ffrt_whitelist.conf vendored Normal file
View File

@ -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
}

54
3rd_party/ffrt/hisysevent.yaml vendored Normal file
View File

@ -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}

46
3rd_party/ffrt/include/core/entity.h vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -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
* 0data represents the root node of this data signature
* 1Non-nested scenes: v1<>v2<>v3<>data
* 2Nested 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

View File

@ -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 */

62
3rd_party/ffrt/include/dfx/bbox/bbox.h vendored Normal file
View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__

View File

@ -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__

View File

@ -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

View File

@ -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__

View File

@ -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

View File

@ -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 */

View File

@ -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

277
3rd_party/ffrt/include/eu/blockaware.h vendored Normal file
View File

@ -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 */

66
3rd_party/ffrt/include/eu/co2_context.h vendored Normal file
View File

@ -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 */

160
3rd_party/ffrt/include/eu/co_routine.h vendored Normal file
View File

@ -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

View File

@ -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

224
3rd_party/ffrt/include/eu/cpu_worker.h vendored Normal file
View File

@ -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

377
3rd_party/ffrt/include/eu/execute_unit.h vendored Normal file
View File

@ -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

View File

@ -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

177
3rd_party/ffrt/include/eu/io_poller.h vendored Normal file
View File

@ -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

View File

@ -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 */

72
3rd_party/ffrt/include/eu/rtg_ioctl.h vendored Normal file
View File

@ -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

View File

@ -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

172
3rd_party/ffrt/include/eu/thread_group.h vendored Normal file
View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

107
3rd_party/ffrt/include/sched/scheduler.h vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

211
3rd_party/ffrt/include/sync/poller.h vendored Normal file
View File

@ -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

99
3rd_party/ffrt/include/sync/sync.h vendored Normal file
View File

@ -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

View File

@ -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

161
3rd_party/ffrt/include/tm/cpu_task.h vendored Normal file
View File

@ -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

86
3rd_party/ffrt/include/tm/io_task.h vendored Normal file
View File

@ -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

194
3rd_party/ffrt/include/tm/queue_task.h vendored Normal file
View File

@ -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

93
3rd_party/ffrt/include/tm/scpu_task.h vendored Normal file
View File

@ -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

221
3rd_party/ffrt/include/tm/task_base.h vendored Normal file
View File

@ -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

135
3rd_party/ffrt/include/tm/task_factory.h vendored Normal file
View File

@ -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

118
3rd_party/ffrt/include/tm/uv_task.h vendored Normal file
View File

@ -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

37
3rd_party/ffrt/include/util/cb_func.h vendored Normal file
View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

360
3rd_party/ffrt/include/util/slab.h vendored Normal file
View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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信息taskqueueworker相关信息.
*
* @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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
/** @} */

View File

@ -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