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 25 #if defined(__aarch64__) 26 constexpr size_t STACK_MAGIC = 0x7BCDABCDABCDABCD; 27 #elif defined(__arm__) 28 constexpr size_t STACK_MAGIC = 0x7BCDABCD; 29 #elif defined(__x86_64__) 30 constexpr size_t STACK_MAGIC = 0x7BCDABCDABCDABCD; 31 #endif 32 33 namespace ffrt { 34 class CPUEUTask; 35 struct WaitEntry; 36 } // namespace ffrt 37 struct CoRoutine; 38 39 enum class CoStatus { 40 CO_UNINITIALIZED, 41 CO_NOT_FINISH, 42 CO_RUNNING, 43 }; 44 45 enum class CoStackProtectType { 46 CO_STACK_WEAK_PROTECT, 47 CO_STACK_STRONG_PROTECT 48 }; 49 50 enum class BlockType { 51 BLOCK_COROUTINE, 52 BLOCK_THREAD 53 }; 54 55 constexpr uint64_t STACK_SIZE = 1 << 20; 56 constexpr uint64_t MIN_STACK_SIZE = 32 * 1024; 57 58 using CoCtx = struct co2_context; 59 60 struct CoRoutineEnv { 61 // when task is running, runningCo same with task->co 62 // if task switch out, set to null. if task complete, be used as co cache for next task. 63 CoRoutine* runningCo = nullptr; 64 CoCtx schCtx; 65 const std::function<bool(ffrt::CPUEUTask*)>* pending = nullptr; 66 }; 67 68 struct StackMem { 69 uint64_t size; 70 size_t magic; 71 uint8_t stk[8]; 72 }; 73 74 struct CoRoutine { 75 std::atomic_int status; 76 CoRoutineEnv* thEnv; 77 ffrt::CPUEUTask* task; 78 CoCtx ctx; 79 uint64_t allocatedSize; // CoRoutine allocated size 80 bool isTaskDone = false; 81 StackMem stkMem; 82 }; 83 84 struct CoStackAttr { 85 public: 86 explicit CoStackAttr(uint64_t coSize = STACK_SIZE, CoStackProtectType coType = 87 CoStackProtectType::CO_STACK_WEAK_PROTECT) 88 { 89 size = coSize; 90 type = coType; 91 } ~CoStackAttrCoStackAttr92 ~CoStackAttr() {} 93 uint64_t size; 94 CoStackProtectType type; 95 96 static inline CoStackAttr* Instance(uint64_t coSize = STACK_SIZE, 97 CoStackProtectType coType = CoStackProtectType::CO_STACK_WEAK_PROTECT) 98 { 99 static CoStackAttr inst(coSize, coType); 100 return &inst; 101 } 102 }; 103 104 class CoRoutineFactory { 105 public: 106 using CowakeCB = std::function<void (ffrt::CPUEUTask*, bool)>; 107 108 static CoRoutineFactory &Instance(); 109 CoWakeFunc(ffrt::CPUEUTask * task,bool timeOut)110 static void CoWakeFunc(ffrt::CPUEUTask* task, bool timeOut) 111 { 112 return Instance().cowake_(task, timeOut); 113 } 114 RegistCb(const CowakeCB & cowake)115 static void RegistCb(const CowakeCB &cowake) 116 { 117 Instance().cowake_ = cowake; 118 } 119 private: 120 CowakeCB cowake_; 121 }; 122 123 void CoStackFree(void); 124 void CoWorkerExit(void); 125 126 int CoStart(ffrt::CPUEUTask* task, CoRoutineEnv* coRoutineEnv); 127 void CoYield(void); 128 129 void CoWait(const std::function<bool(ffrt::CPUEUTask*)>& pred); 130 void CoWake(ffrt::CPUEUTask* task, bool timeOut); 131 132 CoRoutineEnv* GetCoEnv(void); 133 134 #ifdef FFRT_TASK_LOCAL_ENABLE 135 void TaskTsdDeconstruct(ffrt::CPUEUTask* task); 136 #endif 137 138 #endif 139