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
33namespace ffrt {
34namespace this_task {
35CPUEUTask* ExecuteCtxTask()
36{
37    auto ctx = ExecuteCtx::Cur();
38    return ctx->task;
39}
40
41void 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
63extern "C" {
64#endif
65
66API_ATTRIBUTE((visibility("default")))
67void 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);
81    CoWait([](ffrt::CPUEUTask* task) -> bool {
82        CoRoutineFactory::CoWakeFunc(task, false);
83        return true;
84    });
85}
86
87API_ATTRIBUTE((visibility("default")))
88int 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