diff --git a/OAT.xml b/OAT.xml index 0c2b65b4df625c0a46e779ba6576773468e43336..95921d6e8b0383b369112e2734e084ea60e035be 100644 --- a/OAT.xml +++ b/OAT.xml @@ -25,4 +25,4 @@ - \ No newline at end of file + diff --git a/bundle.json b/bundle.json index 29817f761749b88cac792a9ac81176ae8054c717..9db5bf723184f9710b59e20d904cdb7a5422f872 100644 --- a/bundle.json +++ b/bundle.json @@ -32,7 +32,6 @@ "//commonlibrary/memory_utils/libdmabufheap:libdmabufheap", "//commonlibrary/memory_utils/libmeminfo:libmeminfo", "//commonlibrary/memory_utils/libpurgeablemem:libpurgeablemem", - "//commonlibrary/memory_utils/libsync:libsync", "//commonlibrary/memory_utils/libpurgeablemem:purgeable_memory_ndk" ], "inner_kits": [ @@ -54,15 +53,6 @@ "header_base": "//commonlibrary/memory_utils/libmeminfo/include" } }, - { - "name": "//commonlibrary/memory_utils/libsync:libsync", - "header": { - "header_files": [ - "sync.h" - ], - "header_base": "//commonlibrary/memory_utils/libsync/include" - } - }, { "name": "//commonlibrary/memory_utils/libpurgeablemem:libpurgeablemem", "header": { diff --git a/libdmabufheap/src/dmabuf_alloc.c b/libdmabufheap/src/dmabuf_alloc.c index 02dec9d783b5d5e7c35d05b29d442b94e79afdc5..6d759f9ee7e624a5abd1fa84197ca2578f77f87e 100644 --- a/libdmabufheap/src/dmabuf_alloc.c +++ b/libdmabufheap/src/dmabuf_alloc.c @@ -32,11 +32,13 @@ static bool IsHeapNameValid(const char *heapName) { - if ((heapName == NULL) || (strlen(heapName) == 0) || - (strlen(heapName) > HEAP_NAME_MAX_LEN)) { + if (heapName == NULL) { + return false; + } + size_t len = strlen(heapName); + if ((len == 0) || (len > HEAP_NAME_MAX_LEN)) { return false; } - return true; } diff --git a/libpurgeablemem/c/src/purgeable_memory.c b/libpurgeablemem/c/src/purgeable_memory.c index b0cf21b303445adf2c2b6f65d0b7a928fa22e79f..918a6161acf468388871270dbfb0f0f6eaefc763 100644 --- a/libpurgeablemem/c/src/purgeable_memory.c +++ b/libpurgeablemem/c/src/purgeable_memory.c @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "pthread.h" +#include #include "purgeable_mem_builder_c.h" #include "purgeable_mem_c.h" diff --git a/libpurgeablemem/cpp/include/purgeable_mem_base.h b/libpurgeablemem/cpp/include/purgeable_mem_base.h index 1567e85e2f6c72037211f9ced5298bd39ea42849..f9b548711a147748d963ed27325a57828c11fac5 100644 --- a/libpurgeablemem/cpp/include/purgeable_mem_base.h +++ b/libpurgeablemem/cpp/include/purgeable_mem_base.h @@ -39,6 +39,15 @@ public: * While return true if content recover success. * OS cannot reclaim the memory of the obj's content when this * function return true, until EndRead() is called. + * + * Attension: the return value must be recevied and handled, + * since the visiting of this object with the failure result + * will cause unsuspected result. + * For example: + * if (BeginRead()) { + * // visit this object + * EndRead(); + * } */ bool BeginRead(); @@ -50,13 +59,22 @@ public: void EndRead(); /* - * BeginRead: begin read the PurgeableMem obj. + * BeginRead: begin write the PurgeableMem obj. * Return: return true if the obj's content is present. * If content is purged(no present), system will recover its data, * return false if content is purged and recover failed. * While return true if content recover success. * OS cannot reclaim the memory of the obj's content when this - * function return true, until EndRead() is called. + * function return true, until EndWrite() is called. + * + * Attension: the return value must be recevied and handled, + * since the visiting of this object with the failure result + * will cause unsuspected result. + * For example: + * if (BeginWrite()) { + * // visit this object + * EndWrite(); + * } */ bool BeginWrite(); @@ -104,6 +122,8 @@ public: PurgeableMemBase& operator = (PurgeableMemBase&) = delete; PurgeableMemBase(PurgeableMemBase&&) noexcept = delete; PurgeableMemBase& operator = (PurgeableMemBase&&) noexcept = delete; + virtual int GetPinStatus() const; + virtual bool Pin(); protected: void *dataPtr_ = nullptr; @@ -114,10 +134,8 @@ protected: unsigned int buildDataCount_ = 0; bool BuildContent(); bool IfNeedRebuild(); - virtual bool Pin(); virtual bool Unpin(); virtual bool IsPurged(); - virtual int GetPinStatus() const; virtual void AfterRebuildSucc(); virtual std::string ToString() const; }; diff --git a/libpurgeablemem/cpp/src/purgeable_mem_base.cpp b/libpurgeablemem/cpp/src/purgeable_mem_base.cpp index 5fe2900bc45aca141c162b5fb375d1bb3e3bbf27..0c5a9357dac437ad77716ded04e3851dc74a8fe4 100644 --- a/libpurgeablemem/cpp/src/purgeable_mem_base.cpp +++ b/libpurgeablemem/cpp/src/purgeable_mem_base.cpp @@ -97,6 +97,7 @@ bool PurgeableMemBase::BeginRead() void PurgeableMemBase::EndRead() { + std::lock_guard lock(dataLock_); if (isDataValid_) { Unpin(); } @@ -141,6 +142,7 @@ bool PurgeableMemBase::BeginWrite() void PurgeableMemBase::EndWrite() { + std::lock_guard lock(dataLock_); PM_HILOG_DEBUG(LOG_CORE, "%{public}s %{public}s", __func__, ToString().c_str()); Unpin(); } @@ -233,6 +235,7 @@ inline std::string PurgeableMemBase::ToString() const void PurgeableMemBase::SetRebuildSuccessCallback(std::function &callback) { + std::lock_guard lock(dataLock_); if (builder_) { builder_->SetRebuildSuccessCallback(callback); } @@ -240,11 +243,13 @@ void PurgeableMemBase::SetRebuildSuccessCallback(std::function &callback bool PurgeableMemBase::IsDataValid() { + std::lock_guard lock(dataLock_); return isDataValid_; } void PurgeableMemBase::SetDataValid(bool target) { + std::lock_guard lock(dataLock_); isDataValid_ = target; } } /* namespace PurgeableMem */ diff --git a/libpurgeablemem/interfaces/kits/c/purgeable_memory.h b/libpurgeablemem/interfaces/kits/c/purgeable_memory.h index a228044348e33e324aa8c5df8dbb9378534face3..6d87f517e461582397f9c5dfaddb6c73ec76920d 100644 --- a/libpurgeablemem/interfaces/kits/c/purgeable_memory.h +++ b/libpurgeablemem/interfaces/kits/c/purgeable_memory.h @@ -108,6 +108,15 @@ bool OH_PurgeableMemory_Destroy(OH_PurgeableMemory *purgObj); * OS cannot reclaim the memory of @purgObj's content when this * function return true, until PurgMemEndRead() is called. * + * Attension: the return value must be recevied and handled, + * since the visiting of this object with the failure result + * will cause unsuspected result. + * For example: + * if (OH_PurgeableMemory_BeginRead()) { + * // visit this object + * OH_PurgeableMemory_EndRead(); + * } + * * @since 10 * @version 1.0 */ @@ -138,6 +147,15 @@ void OH_PurgeableMemory_EndRead(OH_PurgeableMemory *purgObj); * OS cannot reclaim the memory of @purgObj's content when this * function return true, until PurgMemEndWrite() is called. * + * Attension: the return value must be recevied and handled, + * since the visiting of this object with the failure result + * will cause unsuspected result. + * For example: + * if (OH_PurgeableMemory_BeginWrite()) { + * // visit this object + * OH_PurgeableMemory_EndWrite(); + * } + * * @since 10 * @version 1.0 */ diff --git a/libpurgeablemem/test/BUILD.gn b/libpurgeablemem/test/BUILD.gn index 64e4b125cd972423cd6ac00b8617c1ff829992af..baf20f0cbcfc9786835b4640bfbff26dd9fc4ec4 100644 --- a/libpurgeablemem/test/BUILD.gn +++ b/libpurgeablemem/test/BUILD.gn @@ -45,6 +45,17 @@ ohos_unittest("purgeable_cpp_test") { part_name = "memory_utils" } +ohos_unittest("purgeable_memory_test") { + module_out_path = module_output_path + sources = [ "purgeable_memory_test.cpp" ] + if (is_standard_system) { + external_deps = purgeable_external_deps + } + + subsystem_name = "commonlibrary" + part_name = "memory_utils" +} + ohos_unittest("purgeableashmem_test") { module_out_path = module_output_path sources = [ "purgeableashmem_test.cpp" ] @@ -61,6 +72,7 @@ group("libpurgeablemem_test") { deps = [ ":purgeable_c_test", ":purgeable_cpp_test", + ":purgeable_memory_test", ":purgeableashmem_test", ] } diff --git a/libpurgeablemem/test/purgeable_memory_test.cpp b/libpurgeablemem/test/purgeable_memory_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f2739872f7edbe2b62d6f5062571fd2c15d11e5 --- /dev/null +++ b/libpurgeablemem/test/purgeable_memory_test.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "gtest/gtest.h" +#include "purgeable_memory.h" + +namespace { +using namespace testing; +using namespace testing::ext; + +struct AlphabetInitParam { + char start; + char end; +}; + +struct AlphabetModifyParam { + char src; + char dst; +}; + +static constexpr int PRINT_INTERVAL_SECONDS = 1; +static constexpr int RECLAIM_INTERVAL_SECONDS = 1; +static constexpr int MODIFY_INTERVAL_SECONDS = 2; + +bool InitData(void *data, size_t size, char start, char end); +bool ModifyData(void *data, size_t size, char src, char dst); +bool InitAlphabet(void *data, size_t size, void *param); +bool ModifyAlphabetX2Y(void *data, size_t size, void *param); +void LoopPrintAlphabet(OH_PurgeableMemory *pdata, unsigned int loopCount); +bool ReclaimPurgeable(void); +void LoopReclaimPurgeable(unsigned int loopCount); +void ModifyPurgMemByFunc(OH_PurgeableMemory *pdata, OH_PurgeableMemory_ModifyFunc Modfunc, void *param); + +class PurgeableMemoryTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void PurgeableMemoryTest::SetUpTestCase() +{ +} + +void PurgeableMemoryTest::TearDownTestCase() +{ +} + +void PurgeableMemoryTest::SetUp() +{ +} + +void PurgeableMemoryTest::TearDown() +{ +} + +HWTEST_F(PurgeableMemoryTest, MultiObjCreateTest, TestSize.Level1) +{ + const char alphabetFinal[] = "BBCDEFGHIJKLMNOPQRSTUVWXYZ\0"; + struct AlphabetInitParam initPara = {'A', 'Z'}; + OH_PurgeableMemory *pobj1 = OH_PurgeableMemory_Create(27, InitAlphabet, &initPara); + LoopPrintAlphabet(pobj1, 1); + struct AlphabetModifyParam a2b = {'A', 'B'}; + ModifyPurgMemByFunc(pobj1, ModifyAlphabetX2Y, static_cast(&a2b)); + LoopPrintAlphabet(pobj1, 1); + LoopReclaimPurgeable(1); + + if (OH_PurgeableMemory_BeginRead(pobj1)) { + ASSERT_STREQ(alphabetFinal, static_cast(OH_PurgeableMemory_GetContent(pobj1))); + OH_PurgeableMemory_EndRead(pobj1); + } + + EXPECT_EQ(OH_PurgeableMemory_Destroy(pobj1), true); +} + + +HWTEST_F(PurgeableMemoryTest, WriteTest, TestSize.Level1) +{ + const char alphabet[] = "CCCDEFGHIJKLMNOPQRSTUVWXYZ\0"; + struct AlphabetInitParam initPara = {'A', 'Z'}; + OH_PurgeableMemory *pobj = OH_PurgeableMemory_Create(27, InitAlphabet, &initPara); + LoopReclaimPurgeable(1); + + struct AlphabetModifyParam a2b = {'A', 'B'}; + struct AlphabetModifyParam b2c = {'B', 'C'}; + ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast(&a2b)); + ModifyPurgMemByFunc(pobj, ModifyAlphabetX2Y, static_cast(&b2c)); + + if (OH_PurgeableMemory_BeginRead(pobj)) { + ASSERT_STREQ(alphabet, static_cast(OH_PurgeableMemory_GetContent(pobj))); + OH_PurgeableMemory_EndRead(pobj); + } else { + std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl; + } + + OH_PurgeableMemory_Destroy(pobj); + LoopReclaimPurgeable(3); +} + +bool InitData(void *data, size_t size, char start, char end) +{ + char *str = (char *)data; + size_t len = 0; + for (char ch = start; ch <= end && len < size; ch++) { + str[len++] = ch; + } + str[len] = 0; + return true; +} + +bool InitAlphabet(void *data, size_t size, void *param) +{ + struct AlphabetInitParam *para = (struct AlphabetInitParam *)param; + std::cout << "inter " << __func__ << std::endl; + bool ret = InitData(data, size, para->start, para->end); + std::cout << "quit " << __func__ << ": " << para->start << "-" << para->end << + ", data=[" << (char *)data << "]" << ", ret=" << (ret ? "true" : "false") << std::endl; + return ret; +} + +bool ModifyData(void *data, size_t size, char src, char dst) +{ + char *str = (char *)data; + size_t i = 0; + for (; i < size && str[i]; i++) { + if (str[i] == src) { + str[i] = dst; + } + } + str[i] = 0; + return true; +} + +bool ModifyAlphabetX2Y(void *data, size_t size, void *param) +{ + struct AlphabetModifyParam *para = (struct AlphabetModifyParam *)param; + std::cout << "inter " << __func__ << ": " << para->src << "->" << para->dst << + ", data=[" << (char *)data << "]" << std::endl; + bool ret = ModifyData(data, size, para->src, para->dst); + std::cout << "quit , data=[" << (char *)data << "]" << __func__ << + ", ret=" << (ret ? "true" : "false") << std::endl; + return ret; +} + +void LoopPrintAlphabet(OH_PurgeableMemory *pdata, unsigned int loopCount) +{ + std::cout << "inter " << __func__ << std::endl; + for (unsigned int i = 0; i < loopCount; i++) { + if (!OH_PurgeableMemory_BeginRead(pdata)) { + std::cout << __func__ << ": " << i << ". ERROR! BeginRead failed." << std::endl; + break; + } + std::cout << __func__ << ": " << i << ". data=[" << + (char *)OH_PurgeableMemory_GetContent(pdata) << "]" << std::endl; + OH_PurgeableMemory_EndRead(pdata); + std::this_thread::sleep_for(std::chrono::seconds(PRINT_INTERVAL_SECONDS)); + } + std::cout << "quit " << __func__ << std::endl; +} + +bool ReclaimPurgeable(void) +{ + FILE *f = fopen("/proc/sys/kernel/purgeable", "w"); + if (!f) { + std::cout << __func__ << ": open file failed" << std::endl; + return false; + } + bool succ = true; + if (fputs("1", f) == EOF) { + succ = false; + } + + if (fclose(f) == EOF) { + std::cout << __func__ << ": close file failed" << std::endl; + } + + return succ; +} + +void LoopReclaimPurgeable(unsigned int loopCount) +{ + bool ret = false; + std::cout << "inter " << __func__ << std::endl; + for (unsigned int i = 0; i < loopCount; i++) { + ret = ReclaimPurgeable(); + std::cout << __func__ << ": " << i << ". Reclaim result=" << (ret ? "succ" : "fail") << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(RECLAIM_INTERVAL_SECONDS)); /* wait reclaim finish */ + } + std::cout << "quit " << __func__ << std::endl; +} + +void ModifyPurgMemByFunc(OH_PurgeableMemory *pdata, OH_PurgeableMemory_ModifyFunc Modfunc, void *param) +{ + if (OH_PurgeableMemory_BeginWrite(pdata)) { + std::this_thread::sleep_for(std::chrono::seconds(MODIFY_INTERVAL_SECONDS)); + OH_PurgeableMemory_AppendModify(pdata, Modfunc, param); + std::cout<< __func__ << " after mod data=[" << (char *)OH_PurgeableMemory_GetContent(pdata) << "]" << std::endl; + + std::cout << __func__ << " data=[" << (char *)OH_PurgeableMemory_GetContent(pdata) << "]" << std::endl; + OH_PurgeableMemory_EndWrite(pdata); + } +} +} /* namespace */ diff --git a/libsync/BUILD.gn b/libsync/BUILD.gn deleted file mode 100644 index 13ee1ca214ec6c2838d8a5415c7d47268457c7b7..0000000000000000000000000000000000000000 --- a/libsync/BUILD.gn +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build/ohos.gni") - -config("libsync_config") { - include_dirs = [ "include" ] -} - -ohos_shared_library("libsync") { - sources = [ "src/sync.c" ] - include_dirs = [ "include" ] - - public_configs = [ ":libsync_config" ] - subsystem_name = "commonlibrary" - part_name = "memory_utils" - - sanitize = { - cfi = true - cfi_cross_dso = true - debug = false - } - branch_protector_ret = "pac_ret" -} diff --git a/libsync/include/sync.h b/libsync/include/sync.h deleted file mode 100644 index cf0eabea86110bdda780ebacdf7ddc4114d69c5e..0000000000000000000000000000000000000000 --- a/libsync/include/sync.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef COMM_UTILS_SYNC_H -#define COMM_UTILS_SYNC_H - -int SyncWait(int num, int time); - -#endif \ No newline at end of file diff --git a/libsync/src/sync.c b/libsync/src/sync.c deleted file mode 100644 index 5d216bea3940bc28b7b8f89a473cb2fdc35d660a..0000000000000000000000000000000000000000 --- a/libsync/src/sync.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "sync.h" -#include -#include -#include - -int SyncWait(int num, int time) -{ - struct pollfd work; - int result; - - if (num < 0) { - errno = EINVAL; - return -1; - } - - work.fd = num; - work.events = POLLIN; - - do { - result = poll(&work, 1, time); - if (result > 0) { - if (work.revents & (POLLERR | POLLNVAL)) { - errno = EINVAL; - return -1; - } - return 0; - } else if (result == 0) { - errno = ETIME; - return -1; - } - } while (result == -1 && (errno == EINTR || errno == EAGAIN)); - - return result; -}