• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "dfx/trace/ffrt_trace.h"
30 #include "tm/cpu_task.h"
31 #include "cpp/sleep.h"
32 
33 constexpr uint64_t MAX_US_COUNT = static_cast<uint64_t>(std::chrono::microseconds::max().count());
34 
35 namespace ffrt {
36 namespace this_task {
SleepUntilImpl(const TimePoint & to)37 void SleepUntilImpl(const TimePoint& to)
38 {
39     auto task = ExecuteCtx::Cur()->task;
40     if (task == nullptr || task->Block() == BlockType::BLOCK_THREAD) {
41         std::this_thread::sleep_until(to);
42         if (task) {
43             task->Wake();
44         }
45         return;
46     }
47     // be careful about local-var use-after-free here
48     static std::function<void(WaitEntry*)> cb ([](WaitEntry* we) {
49         CoRoutineFactory::CoWakeFunc(static_cast<CoTask*>(we->task), CoWakeType::NO_TIMEOUT_WAKE);
50     });
51     FFRT_BLOCK_TRACER(ExecuteCtx::Cur()->task->gid, slp);
52     CoWait([&](CoTask* task) -> bool {
53         return DelayedWakeup(to, &task->we, cb);
54     });
55 }
56 }
57 } // namespace ffrt
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 
63 API_ATTRIBUTE((visibility("default")))
ffrt_yield()64 void ffrt_yield()
65 {
66     auto curTask = ffrt::ExecuteCtx::Cur()->task;
67     if (curTask == nullptr || curTask->Block() == ffrt::BlockType::BLOCK_THREAD) {
68         std::this_thread::yield();
69         if (curTask) {
70             curTask->Wake();
71         }
72         return;
73     }
74     FFRT_BLOCK_TRACER(curTask->gid, yld);
75     CoWait([](ffrt::CoTask* task) -> bool {
76         CoRoutineFactory::CoWakeFunc(task, CoWakeType::NO_TIMEOUT_WAKE);
77         return true;
78     });
79 }
80 
81 API_ATTRIBUTE((visibility("default")))
ffrt_usleep(uint64_t usec)82 int ffrt_usleep(uint64_t usec)
83 {
84     if (usec > MAX_US_COUNT) {
85         FFRT_LOGW("usec exceeds maximum allowed value %llu us. Clamping to %llu us.", usec, MAX_US_COUNT);
86         usec = MAX_US_COUNT;
87     }
88 
89     auto now = std::chrono::steady_clock::now();
90     auto nowUs = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch());
91     auto sleepUs = std::chrono::microseconds(usec);
92     std::chrono::steady_clock::time_point to;
93     if (sleepUs.count() > (std::chrono::microseconds::max().count() - nowUs.count())) {
94         to = std::chrono::steady_clock::time_point::max();
95     } else {
96         to = now + sleepUs;
97     }
98 
99     ffrt::this_task::SleepUntilImpl(to);
100     return ffrt_success;
101 }
102 
103 #ifdef __cplusplus
104 }
105 #endif