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