1f0bfeaa8Sopenharmony_ci/* 2f0bfeaa8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3f0bfeaa8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4f0bfeaa8Sopenharmony_ci * you may not use this file except in compliance with the License. 5f0bfeaa8Sopenharmony_ci * You may obtain a copy of the License at 6f0bfeaa8Sopenharmony_ci * 7f0bfeaa8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8f0bfeaa8Sopenharmony_ci * 9f0bfeaa8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10f0bfeaa8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11f0bfeaa8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f0bfeaa8Sopenharmony_ci * See the License for the specific language governing permissions and 13f0bfeaa8Sopenharmony_ci * limitations under the License. 14f0bfeaa8Sopenharmony_ci */ 15f0bfeaa8Sopenharmony_ci 16f0bfeaa8Sopenharmony_ci#include <sys/mman.h> /* mmap */ 17f0bfeaa8Sopenharmony_ci 18f0bfeaa8Sopenharmony_ci#include "securec.h" 19f0bfeaa8Sopenharmony_ci#include "pm_util.h" 20f0bfeaa8Sopenharmony_ci#include "pm_state_c.h" 21f0bfeaa8Sopenharmony_ci#include "pm_smartptr_util.h" 22f0bfeaa8Sopenharmony_ci#include "pm_log.h" 23f0bfeaa8Sopenharmony_ci 24f0bfeaa8Sopenharmony_ci#include "purgeable_mem_base.h" 25f0bfeaa8Sopenharmony_ci 26f0bfeaa8Sopenharmony_cinamespace OHOS { 27f0bfeaa8Sopenharmony_cinamespace PurgeableMem { 28f0bfeaa8Sopenharmony_ci#ifdef LOG_TAG 29f0bfeaa8Sopenharmony_ci#undef LOG_TAG 30f0bfeaa8Sopenharmony_ci#endif 31f0bfeaa8Sopenharmony_ci#define LOG_TAG "PurgeableMem" 32f0bfeaa8Sopenharmony_ciconst int MAX_BUILD_TRYTIMES = 3; 33f0bfeaa8Sopenharmony_ci 34f0bfeaa8Sopenharmony_cistatic inline size_t RoundUp(size_t val, size_t align) 35f0bfeaa8Sopenharmony_ci{ 36f0bfeaa8Sopenharmony_ci if (val + align < val || val + align < align) { 37f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: Addition overflow!", __func__); 38f0bfeaa8Sopenharmony_ci return val; 39f0bfeaa8Sopenharmony_ci } 40f0bfeaa8Sopenharmony_ci if (align == 0) { 41f0bfeaa8Sopenharmony_ci return val; 42f0bfeaa8Sopenharmony_ci } 43f0bfeaa8Sopenharmony_ci return ((val + align - 1) / align) * align; 44f0bfeaa8Sopenharmony_ci} 45f0bfeaa8Sopenharmony_ci 46f0bfeaa8Sopenharmony_ciPurgeableMemBase::PurgeableMemBase() 47f0bfeaa8Sopenharmony_ci{ 48f0bfeaa8Sopenharmony_ci} 49f0bfeaa8Sopenharmony_ci 50f0bfeaa8Sopenharmony_ciPurgeableMemBase::~PurgeableMemBase() 51f0bfeaa8Sopenharmony_ci{ 52f0bfeaa8Sopenharmony_ci} 53f0bfeaa8Sopenharmony_ci 54f0bfeaa8Sopenharmony_cibool PurgeableMemBase::BeginRead() 55f0bfeaa8Sopenharmony_ci{ 56f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 57f0bfeaa8Sopenharmony_ci if (!isDataValid_) { 58f0bfeaa8Sopenharmony_ci return false; 59f0bfeaa8Sopenharmony_ci } 60f0bfeaa8Sopenharmony_ci 61f0bfeaa8Sopenharmony_ci bool ret = false; 62f0bfeaa8Sopenharmony_ci int tryTimes = 0; 63f0bfeaa8Sopenharmony_ci 64f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s %{public}s", __func__, ToString().c_str()); 65f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(dataPtr_, "dataPtr is nullptr in BeginRead", return false); 66f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(builder_, "builder_ is nullptr in BeginRead", return false); 67f0bfeaa8Sopenharmony_ci Pin(); 68f0bfeaa8Sopenharmony_ci PMState err = PM_OK; 69f0bfeaa8Sopenharmony_ci while (true) { 70f0bfeaa8Sopenharmony_ci if (!IfNeedRebuild()) { 71f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s: not purged, return true. MAP_PUR=0x%{public}x", 72f0bfeaa8Sopenharmony_ci __func__, MAP_PURGEABLE); 73f0bfeaa8Sopenharmony_ci ret = true; 74f0bfeaa8Sopenharmony_ci break; 75f0bfeaa8Sopenharmony_ci } 76f0bfeaa8Sopenharmony_ci 77f0bfeaa8Sopenharmony_ci bool succ = BuildContent(); 78f0bfeaa8Sopenharmony_ci if (succ) { 79f0bfeaa8Sopenharmony_ci AfterRebuildSucc(); 80f0bfeaa8Sopenharmony_ci } 81f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s: purged, built %{public}s", __func__, succ ? "succ" : "fail"); 82f0bfeaa8Sopenharmony_ci 83f0bfeaa8Sopenharmony_ci tryTimes++; 84f0bfeaa8Sopenharmony_ci if (!succ || tryTimes > MAX_BUILD_TRYTIMES) { 85f0bfeaa8Sopenharmony_ci err = PMB_BUILD_ALL_FAIL; 86f0bfeaa8Sopenharmony_ci break; 87f0bfeaa8Sopenharmony_ci } 88f0bfeaa8Sopenharmony_ci } 89f0bfeaa8Sopenharmony_ci 90f0bfeaa8Sopenharmony_ci if (!ret) { 91f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: err %{public}s, UxptePut. tryTime:%{public}d", 92f0bfeaa8Sopenharmony_ci __func__, GetPMStateName(err), tryTimes); 93f0bfeaa8Sopenharmony_ci Unpin(); 94f0bfeaa8Sopenharmony_ci } 95f0bfeaa8Sopenharmony_ci return ret; 96f0bfeaa8Sopenharmony_ci} 97f0bfeaa8Sopenharmony_ci 98f0bfeaa8Sopenharmony_civoid PurgeableMemBase::EndRead() 99f0bfeaa8Sopenharmony_ci{ 100f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 101f0bfeaa8Sopenharmony_ci if (isDataValid_) { 102f0bfeaa8Sopenharmony_ci Unpin(); 103f0bfeaa8Sopenharmony_ci } 104f0bfeaa8Sopenharmony_ci 105f0bfeaa8Sopenharmony_ci return; 106f0bfeaa8Sopenharmony_ci} 107f0bfeaa8Sopenharmony_ci 108f0bfeaa8Sopenharmony_cibool PurgeableMemBase::BeginWrite() 109f0bfeaa8Sopenharmony_ci{ 110f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s %{public}s", __func__, ToString().c_str()); 111f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 112f0bfeaa8Sopenharmony_ci if (dataPtr_ == nullptr) { 113f0bfeaa8Sopenharmony_ci return false; 114f0bfeaa8Sopenharmony_ci } 115f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(dataPtr_, "dataPtr is nullptr in BeginWrite", return false); 116f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(builder_, "builder_ is nullptr in BeginWrite", return false); 117f0bfeaa8Sopenharmony_ci 118f0bfeaa8Sopenharmony_ci Pin(); 119f0bfeaa8Sopenharmony_ci PMState err = PM_OK; 120f0bfeaa8Sopenharmony_ci do { 121f0bfeaa8Sopenharmony_ci if (!IfNeedRebuild()) { 122f0bfeaa8Sopenharmony_ci /* data is not purged, return true */ 123f0bfeaa8Sopenharmony_ci break; 124f0bfeaa8Sopenharmony_ci } 125f0bfeaa8Sopenharmony_ci /* data purged, rebuild it */ 126f0bfeaa8Sopenharmony_ci if (BuildContent()) { 127f0bfeaa8Sopenharmony_ci /* data rebuild succ, return true */ 128f0bfeaa8Sopenharmony_ci AfterRebuildSucc(); 129f0bfeaa8Sopenharmony_ci break; 130f0bfeaa8Sopenharmony_ci } 131f0bfeaa8Sopenharmony_ci err = PMB_BUILD_ALL_FAIL; 132f0bfeaa8Sopenharmony_ci } while (0); 133f0bfeaa8Sopenharmony_ci 134f0bfeaa8Sopenharmony_ci if (err == PM_OK) { 135f0bfeaa8Sopenharmony_ci return true; 136f0bfeaa8Sopenharmony_ci } 137f0bfeaa8Sopenharmony_ci 138f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: err %{public}s, UxptePut.", __func__, GetPMStateName(err)); 139f0bfeaa8Sopenharmony_ci Unpin(); 140f0bfeaa8Sopenharmony_ci return false; 141f0bfeaa8Sopenharmony_ci} 142f0bfeaa8Sopenharmony_ci 143f0bfeaa8Sopenharmony_civoid PurgeableMemBase::EndWrite() 144f0bfeaa8Sopenharmony_ci{ 145f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 146f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s %{public}s", __func__, ToString().c_str()); 147f0bfeaa8Sopenharmony_ci Unpin(); 148f0bfeaa8Sopenharmony_ci} 149f0bfeaa8Sopenharmony_ci 150f0bfeaa8Sopenharmony_cibool PurgeableMemBase::ModifyContentByBuilder(std::unique_ptr<PurgeableMemBuilder> modifier) 151f0bfeaa8Sopenharmony_ci{ 152f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(modifier, "input modifier is nullptr", return false); 153f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 154f0bfeaa8Sopenharmony_ci if (!modifier->Build(dataPtr_, dataSizeInput_)) { 155f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: modify content by builder fail!!", __func__); 156f0bfeaa8Sopenharmony_ci return false; 157f0bfeaa8Sopenharmony_ci } 158f0bfeaa8Sopenharmony_ci /* log modify */ 159f0bfeaa8Sopenharmony_ci if (builder_) { 160f0bfeaa8Sopenharmony_ci builder_->AppendBuilder(std::move(modifier)); 161f0bfeaa8Sopenharmony_ci } else { 162f0bfeaa8Sopenharmony_ci builder_ = std::move(modifier); 163f0bfeaa8Sopenharmony_ci } 164f0bfeaa8Sopenharmony_ci return true; 165f0bfeaa8Sopenharmony_ci} 166f0bfeaa8Sopenharmony_ci 167f0bfeaa8Sopenharmony_cibool PurgeableMemBase::IfNeedRebuild() 168f0bfeaa8Sopenharmony_ci{ 169f0bfeaa8Sopenharmony_ci if (buildDataCount_ == 0 || IsPurged()) { 170f0bfeaa8Sopenharmony_ci return true; 171f0bfeaa8Sopenharmony_ci } 172f0bfeaa8Sopenharmony_ci return false; 173f0bfeaa8Sopenharmony_ci} 174f0bfeaa8Sopenharmony_ci 175f0bfeaa8Sopenharmony_civoid PurgeableMemBase::AfterRebuildSucc() 176f0bfeaa8Sopenharmony_ci{ 177f0bfeaa8Sopenharmony_ci} 178f0bfeaa8Sopenharmony_ci 179f0bfeaa8Sopenharmony_civoid *PurgeableMemBase::GetContent() 180f0bfeaa8Sopenharmony_ci{ 181f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 182f0bfeaa8Sopenharmony_ci return dataPtr_; 183f0bfeaa8Sopenharmony_ci} 184f0bfeaa8Sopenharmony_ci 185f0bfeaa8Sopenharmony_cisize_t PurgeableMemBase::GetContentSize() 186f0bfeaa8Sopenharmony_ci{ 187f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 188f0bfeaa8Sopenharmony_ci return dataSizeInput_; 189f0bfeaa8Sopenharmony_ci} 190f0bfeaa8Sopenharmony_ci 191f0bfeaa8Sopenharmony_cibool PurgeableMemBase::IsPurged() 192f0bfeaa8Sopenharmony_ci{ 193f0bfeaa8Sopenharmony_ci return false; 194f0bfeaa8Sopenharmony_ci} 195f0bfeaa8Sopenharmony_ci 196f0bfeaa8Sopenharmony_cibool PurgeableMemBase::BuildContent() 197f0bfeaa8Sopenharmony_ci{ 198f0bfeaa8Sopenharmony_ci bool succ = false; 199f0bfeaa8Sopenharmony_ci /* clear content before rebuild */ 200f0bfeaa8Sopenharmony_ci if (memset_s(dataPtr_, RoundUp(dataSizeInput_, PAGE_SIZE), 0, dataSizeInput_) != EOK) { 201f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s, clear content fail", __func__); 202f0bfeaa8Sopenharmony_ci return succ; 203f0bfeaa8Sopenharmony_ci } 204f0bfeaa8Sopenharmony_ci /* builder_ and dataPtr_ is never nullptr since it is checked by BeginAccess() before */ 205f0bfeaa8Sopenharmony_ci succ = builder_->BuildAll(dataPtr_, dataSizeInput_); 206f0bfeaa8Sopenharmony_ci if (succ) { 207f0bfeaa8Sopenharmony_ci buildDataCount_++; 208f0bfeaa8Sopenharmony_ci } 209f0bfeaa8Sopenharmony_ci return succ; 210f0bfeaa8Sopenharmony_ci} 211f0bfeaa8Sopenharmony_ci 212f0bfeaa8Sopenharmony_civoid PurgeableMemBase::ResizeData(size_t newSize) 213f0bfeaa8Sopenharmony_ci{ 214f0bfeaa8Sopenharmony_ci} 215f0bfeaa8Sopenharmony_ci 216f0bfeaa8Sopenharmony_cibool PurgeableMemBase::Pin() 217f0bfeaa8Sopenharmony_ci{ 218f0bfeaa8Sopenharmony_ci return false; 219f0bfeaa8Sopenharmony_ci} 220f0bfeaa8Sopenharmony_ci 221f0bfeaa8Sopenharmony_cibool PurgeableMemBase::Unpin() 222f0bfeaa8Sopenharmony_ci{ 223f0bfeaa8Sopenharmony_ci return false; 224f0bfeaa8Sopenharmony_ci} 225f0bfeaa8Sopenharmony_ci 226f0bfeaa8Sopenharmony_ciint PurgeableMemBase::GetPinStatus() const 227f0bfeaa8Sopenharmony_ci{ 228f0bfeaa8Sopenharmony_ci return 0; 229f0bfeaa8Sopenharmony_ci} 230f0bfeaa8Sopenharmony_ci 231f0bfeaa8Sopenharmony_ciinline std::string PurgeableMemBase::ToString() const 232f0bfeaa8Sopenharmony_ci{ 233f0bfeaa8Sopenharmony_ci return ""; 234f0bfeaa8Sopenharmony_ci} 235f0bfeaa8Sopenharmony_ci 236f0bfeaa8Sopenharmony_civoid PurgeableMemBase::SetRebuildSuccessCallback(std::function<void()> &callback) 237f0bfeaa8Sopenharmony_ci{ 238f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 239f0bfeaa8Sopenharmony_ci if (builder_) { 240f0bfeaa8Sopenharmony_ci builder_->SetRebuildSuccessCallback(callback); 241f0bfeaa8Sopenharmony_ci } 242f0bfeaa8Sopenharmony_ci} 243f0bfeaa8Sopenharmony_ci 244f0bfeaa8Sopenharmony_cibool PurgeableMemBase::IsDataValid() 245f0bfeaa8Sopenharmony_ci{ 246f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 247f0bfeaa8Sopenharmony_ci return isDataValid_; 248f0bfeaa8Sopenharmony_ci} 249f0bfeaa8Sopenharmony_ci 250f0bfeaa8Sopenharmony_civoid PurgeableMemBase::SetDataValid(bool target) 251f0bfeaa8Sopenharmony_ci{ 252f0bfeaa8Sopenharmony_ci std::lock_guard<std::mutex> lock(dataLock_); 253f0bfeaa8Sopenharmony_ci isDataValid_ = target; 254f0bfeaa8Sopenharmony_ci} 255f0bfeaa8Sopenharmony_ci} /* namespace PurgeableMem */ 256f0bfeaa8Sopenharmony_ci} /* namespace OHOS */ 257