* 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 _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <map>
#include <functional>
#include "sync/sync.h"
#include "sched/execute_ctx.h"
#include "eu/co_routine.h"
#include "internal_inc/osal.h"
#include "internal_inc/types.h"
#include "dfx/log/ffrt_log_api.h"
#include "dfx/trace/ffrt_trace.h"
#include "tm/cpu_task.h"
#include "cpp/sleep.h"
constexpr uint64_t MAX_US_COUNT = static_cast<uint64_t>(std::chrono::microseconds::max().count());
namespace ffrt {
namespace this_task {
void SleepUntilImpl(const TimePoint& to)
{
auto task = ExecuteCtx::Cur()->task;
if (task == nullptr || task->Block() == BlockType::BLOCK_THREAD) {
std::this_thread::sleep_until(to);
if (task) {
task->Wake();
}
return;
}
static std::function<void(WaitEntry*)> cb ([](WaitEntry* we) {
CoWake(static_cast<CoTask*>(we->task), CoWakeType::NO_TIMEOUT_WAKE);
});
FFRT_BLOCK_TRACER(ExecuteCtx::Cur()->task->gid, slp);
CoWait([&](CoTask* task) -> bool {
return DelayedWakeup(to, &task->we, cb);
});
}
}
}
#ifdef __cplusplus
extern "C" {
#endif
API_ATTRIBUTE((visibility("default")))
void ffrt_yield()
{
auto curTask = ffrt::ExecuteCtx::Cur()->task;
if (curTask == nullptr || curTask->Block() == ffrt::BlockType::BLOCK_THREAD) {
std::this_thread::yield();
if (curTask) {
curTask->Wake();
}
return;
}
FFRT_BLOCK_TRACER(curTask->gid, yld);
CoWait([](ffrt::CoTask* task) -> bool {
CoWake(task, CoWakeType::NO_TIMEOUT_WAKE);
return true;
});
}
API_ATTRIBUTE((visibility("default")))
int ffrt_usleep(uint64_t usec)
{
if (usec > MAX_US_COUNT) {
FFRT_LOGW("usec exceeds maximum allowed value %llu us. Clamping to %llu us.", usec, MAX_US_COUNT);
usec = MAX_US_COUNT;
}
auto now = std::chrono::steady_clock::now();
auto nowUs = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch());
auto sleepUs = std::chrono::microseconds(usec);
std::chrono::steady_clock::time_point to;
if (sleepUs.count() > (std::chrono::microseconds::max().count() - nowUs.count())) {
to = std::chrono::steady_clock::time_point::max();
} else {
to = now + sleepUs;
}
ffrt::this_task::SleepUntilImpl(to);
return ffrt_success;
}
#ifdef __cplusplus
}
#endif