1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef _GNU_SOURCE
17 #define _GNU_SOURCE
18 #endif
19
20 #include <map>
21 #include <functional>
22 #include "sync/sync.h"
23
24 #include "sched/execute_ctx.h"
25 #include "eu/co_routine.h"
26 #include "internal_inc/osal.h"
27 #include "internal_inc/types.h"
28 #include "dfx/log/ffrt_log_api.h"
29 #include "ffrt_trace.h"
30 #include "tm/cpu_task.h"
31 #include "cpp/sleep.h"
32
33 namespace ffrt {
34 namespace this_task {
ExecuteCtxTask()35 CPUEUTask* ExecuteCtxTask()
36 {
37 auto ctx = ExecuteCtx::Cur();
38 return ctx->task;
39 }
40
SleepUntilImpl(const TimePoint & to)41 void SleepUntilImpl(const TimePoint& to)
42 {
43 auto task = ExecuteCtxTask();
44 if (ThreadWaitMode(task)) {
45 if (FFRT_UNLIKELY(LegacyMode(task))) {
46 task->blockType = BlockType::BLOCK_THREAD;
47 }
48 std::this_thread::sleep_until(to);
49 if (BlockThread(task)) {
50 task->blockType = BlockType::BLOCK_COROUTINE;
51 }
52 return;
53 }
54 // be careful about local-var use-after-free here
55 static std::function<void(WaitEntry*)> cb([](WaitEntry* we) { CoRoutineFactory::CoWakeFunc(we->task, false); });
56 FFRT_BLOCK_TRACER(ExecuteCtxTask()->gid, slp);
57 CoWait([&](CPUEUTask* task) -> bool { return DelayedWakeup(to, &task->fq_we, cb); });
58 }
59 }
60 } // namespace ffrt
61
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65
66 API_ATTRIBUTE((visibility("default")))
67 void ffrt_yield()
68 {
69 auto curTask = ffrt::this_task::ExecuteCtxTask();
70 if (ThreadWaitMode(curTask)) {
71 if (FFRT_UNLIKELY(LegacyMode(curTask))) {
72 curTask->blockType = BlockType::BLOCK_THREAD;
73 }
74 std::this_thread::yield();
75 if (BlockThread(curTask)) {
76 curTask->blockType = BlockType::BLOCK_COROUTINE;
77 }
78 return;
79 }
80 FFRT_BLOCK_TRACER(curTask->gid, yld);
__anondab030b90302(ffrt::CPUEUTask* task) 81 CoWait([](ffrt::CPUEUTask* task) -> bool {
82 CoRoutineFactory::CoWakeFunc(task, false);
83 return true;
84 });
85 }
86
87 API_ATTRIBUTE((visibility("default")))
88 int ffrt_usleep(uint64_t usec)
89 {
90 auto duration = std::chrono::microseconds{usec};
91 auto to = std::chrono::steady_clock::now() + duration;
92
93 ffrt::this_task::SleepUntilImpl(to);
94 return ffrt_success;
95 }
96
97 #ifdef __cplusplus
98 }
99 #endif