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