• 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 FFRT_CO_ROUTINE_HPP
17 #define FFRT_CO_ROUTINE_HPP
18 #include <atomic>
19 #include <functional>
20 #include <thread>
21 #include <pthread.h>
22 #include "co2_context.h"
23 
24 #if defined(__aarch64__)
25 constexpr size_t STACK_MAGIC = 0x7BCDABCDABCDABCD;
26 #elif defined(__arm__)
27 constexpr size_t STACK_MAGIC = 0x7BCDABCD;
28 #elif defined(__x86_64__)
29 constexpr size_t STACK_MAGIC = 0x7BCDABCDABCDABCD;
30 #endif
31 
32 #ifndef FFRT_STACK_SIZE
33 #define FFRT_STACK_SIZE (1 << 20)
34 #endif
35 
36 #ifdef ASAN_MODE
37 extern "C" void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size);
38 extern "C" void __sanitizer_finish_switch_fiber(void *fake_stack_save, const void **bottom_old, size_t *size_old);
39 extern "C" void __asan_handle_no_return();
40 #endif
41 
42 namespace ffrt {
43 class CPUEUTask;
44 struct WaitEntry;
45 } // namespace ffrt
46 struct CoRoutine;
47 
48 enum class CoStatus {
49     CO_UNINITIALIZED,
50     CO_NOT_FINISH,
51     CO_RUNNING,
52 };
53 
54 enum class CoStackProtectType {
55     CO_STACK_WEAK_PROTECT,
56     CO_STACK_STRONG_PROTECT
57 };
58 
59 enum class BlockType {
60     BLOCK_COROUTINE,
61     BLOCK_THREAD
62 };
63 
64 enum class CoWakeType {
65     TIMEOUT_WAKE,
66     NO_TIMEOUT_WAKE
67 };
68 
69 constexpr uint64_t STACK_SIZE = FFRT_STACK_SIZE;
70 constexpr uint64_t MIN_STACK_SIZE = 32 * 1024;
71 constexpr uint64_t STACK_MEM_SIZE = 8;
72 
73 using CoCtx = struct co2_context;
74 
75 struct CoRoutineEnv {
76     // when task is running, runningCo same with task->co
77     // if task switch out, set to null. if task complete, be used as co cache for next task.
78     CoRoutine* runningCo = nullptr;
79     CoCtx schCtx;
80     const std::function<bool(ffrt::CPUEUTask*)>* pending = nullptr;
81 };
82 
83 struct StackMem {
84     uint64_t size;
85     size_t magic;
86     uint8_t stk[STACK_MEM_SIZE];
87 };
88 
89 struct CoRoutine {
90     std::atomic_int status;
91     CoRoutineEnv* thEnv;
92     ffrt::CPUEUTask* task;
93 #ifdef ASAN_MODE
94     void *asanFakeStack = nullptr;  // not finished, need further verification
95     const void *asanFiberAddr = nullptr;
96     size_t asanFiberSize = 0;
97 #endif
98     CoCtx ctx;
99     uint64_t allocatedSize; // CoRoutine allocated size
100     bool isTaskDone = false;
101     /* do not add item after stkMem */
102     StackMem stkMem;
103 };
104 
105 struct CoStackAttr {
106 public:
107     explicit CoStackAttr(uint64_t coSize = STACK_SIZE, CoStackProtectType coType =
108         CoStackProtectType::CO_STACK_WEAK_PROTECT)
109     {
110         size = coSize;
111         type = coType;
112     }
~CoStackAttrCoStackAttr113     ~CoStackAttr() {}
114     uint64_t size;
115     CoStackProtectType type;
116 
117     static inline CoStackAttr* Instance(uint64_t coSize = STACK_SIZE,
118         CoStackProtectType coType = CoStackProtectType::CO_STACK_WEAK_PROTECT)
119     {
120         static CoStackAttr inst(coSize, coType);
121         return &inst;
122     }
123 };
124 
125 class CoRoutineFactory {
126 public:
127     using CowakeCB = std::function<void (ffrt::CPUEUTask*, CoWakeType)>;
128 
129     static CoRoutineFactory &Instance();
130 
CoWakeFunc(ffrt::CPUEUTask * task,CoWakeType type)131     static void CoWakeFunc(ffrt::CPUEUTask* task, CoWakeType type)
132     {
133         return Instance().cowake_(task, type);
134     }
135 
RegistCb(const CowakeCB & cowake)136     static void RegistCb(const CowakeCB &cowake)
137     {
138         Instance().cowake_ = cowake;
139     }
140 private:
141     CowakeCB cowake_;
142 };
143 
144 void CoStackFree(void);
145 void CoWorkerExit(void);
146 
147 int CoStart(ffrt::CPUEUTask* task, CoRoutineEnv* coRoutineEnv);
148 void CoYield(void);
149 
150 void CoWait(const std::function<bool(ffrt::CPUEUTask*)>& pred);
151 void CoWake(ffrt::CPUEUTask* task, CoWakeType type);
152 
153 CoRoutineEnv* GetCoEnv(void);
154 
GetCoStackAddr(CoRoutine * co)155 inline void* GetCoStackAddr(CoRoutine* co)
156 {
157     return static_cast<void*>(reinterpret_cast<char*>(co) + sizeof(CoRoutine) - STACK_MEM_SIZE);
158 }
159 
160 #ifdef FFRT_TASK_LOCAL_ENABLE
161 void TaskTsdDeconstruct(ffrt::CPUEUTask* task);
162 #endif
163 
164 #endif
165