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#include "core/version_ctx.h" 17#include "core/entity.h" 18#include "util/slab.h" 19#include "ffrt_trace.h" 20 21namespace ffrt { 22static inline void BuildConsumeRelationship(VersionCtx* version, SCPUEUTask* consumer) 23{ 24 if (version->status == DataStatus::IDLE) { 25 consumer->IncDepRef(); 26 } 27 version->consumers.insert(consumer); 28 if (version->status == DataStatus::CONSUMED) { 29 version->status = DataStatus::READY; 30 } 31} 32 33static inline void BuildProducerProducerRelationship(VersionCtx* preVersion, SCPUEUTask* nextProducer) 34{ 35 if (preVersion->status != DataStatus::CONSUMED) { 36 preVersion->nextProducer = nextProducer; 37 nextProducer->IncDepRef(); 38 } 39} 40 41void VersionCtx::AddConsumer(SCPUEUTask* consumer, NestType nestType) 42{ 43 FFRT_TRACE_SCOPE(2, AddConsumer); 44 // Parent's VersionCtx 45 VersionCtx* beConsumeVersion = this; 46 if (nestType == NestType::PARENTOUT || nestType == NestType::DEFAULT) { 47 // Create READY version when last is nullptr 48 if (last == nullptr) { 49 CreateChildVersion(consumer, DataStatus::READY); 50 } 51 beConsumeVersion = last; 52 } 53 BuildConsumeRelationship(beConsumeVersion, consumer); 54 consumer->ins.insert(beConsumeVersion); 55} 56 57void VersionCtx::AddProducer(SCPUEUTask* producer) 58{ 59 FFRT_TRACE_SCOPE(2, AddAddProducer); 60 // Parent's VersionCtx 61 auto parentVersion = this; 62 if (parentVersion->last != nullptr) { 63 VersionCtx* preVersion = parentVersion->last; 64 BuildProducerProducerRelationship(preVersion, producer); 65 } 66 parentVersion->CreateChildVersion(producer, DataStatus::IDLE); 67 producer->outs.insert(parentVersion->last); 68 parentVersion->last->myProducer = producer; 69} 70 71void VersionCtx::onProduced() 72{ 73 /* No merge operation, merge operation can only occur when the parent version is produced and 74 * the last child version is not in the CONSUMED state 75 */ 76 if (last == nullptr || last->status == DataStatus::CONSUMED) { 77 // No consumers, directly into CONSUMED after being produced 78 if (consumers.empty()) { 79 status = DataStatus::CONSUMED; 80 NotifyNextProducer(); 81 Entity::Instance()->versionTrashcan.push_back(this); 82 } else { // if have consumers,notify them 83 status = DataStatus::READY; 84 NotifyConsumers(); 85 } 86 NotifyDataWaitTask(); 87 } else { // Merge previous VersionCtx 88 MergeChildVersion(); 89 } 90} 91 92void VersionCtx::onConsumed(SCPUEUTask* consumer) 93{ 94 auto it = std::as_const(consumers).find(consumer); 95 if (it != consumers.end()) { 96 consumers.erase(it); 97 } 98 if (consumers.empty()) { 99 status = DataStatus::CONSUMED; 100 NotifyNextProducer(); 101 Entity::Instance()->versionTrashcan.push_back(this); 102 } 103} 104 105void VersionCtx::CreateChildVersion(SCPUEUTask* task __attribute__((unused)), DataStatus dataStatus) 106{ 107 // Add VersionCtx 108 auto prev = last; 109 last = new (SimpleAllocator<VersionCtx>::AllocMem()) VersionCtx(this->signature, this, prev); 110 last->status = dataStatus; 111 if (prev != nullptr) { 112 prev->next = last; 113 } 114} 115 116void VersionCtx::MergeChildVersion() 117{ 118 // Merge VersionCtx 119 auto versionToMerge = last; 120 status = versionToMerge->status; 121 if (status == DataStatus::READY) { 122 NotifyConsumers(); 123 NotifyDataWaitTask(); 124 } 125 MergeConsumerInDep(versionToMerge); 126 if (status == DataStatus::IDLE) { 127 consumers.insert(versionToMerge->consumers.cbegin(), versionToMerge->consumers.cend()); 128 MergeProducerOutDep(versionToMerge); 129 myProducer = versionToMerge->myProducer; 130 } 131 Entity::Instance()->versionTrashcan.push_back(versionToMerge); 132} 133} /* namespace ffrt */