diff --git a/BUILD.gn b/BUILD.gn index c3c29b11a084e12e630ced9c3ea8d271e054ce56..0ba994180aa4d6226317572ee70ace0ef5a1dabc 100755 --- a/BUILD.gn +++ b/BUILD.gn @@ -22,6 +22,8 @@ config("glib_config") { "glib", "glib/deprecated", "//third_party/gettext/gettext-runtime/intl", + "//foundation/multimedia/media_standard/services/utils", + "glibmemdfx", ] cflags = [ "-DG_LOG_DOMAIN=\"GLib\"", @@ -170,7 +172,9 @@ ohos_shared_library("glib") { deps = [ ":glib_source", "//third_party/gettext:libintl", + ":g_mem_dfx", ] + part_name = "multimedia_media_standard" subsystem_name = "multimedia" } @@ -625,3 +629,59 @@ ohos_static_library("ginotify") { part_name = "multimedia_media_standard" subsystem_name = "multimedia" } + +config("g_mem_dfx_config") { + include_dirs = [ + "glibmemdfx", + "//utils/native/base/include", + "//foundation/multimedia/media_standard/interfaces/inner_api/native", + "//base/hiviewdfx/hisysevent/interfaces/native/innerkits/hisysevent/include", + ] +} + +ohos_shared_library("g_mem_dfx") { + install_enable = true + + sources = [ + "glibmemdfx/gmemdfx.cpp", + ] + + include_dirs = [ + "//utils/native/base/include", + ] + + cflags = [ + "-std=c++17", + "-fno-rtti", + "-fno-exceptions", + "-Wall", + "-fno-common", + "-fstack-protector-strong", + "-Wshadow", + "-FPIC", + "-FS", + "-O2", + "-D_FORTIFY_SOURCE=2", + "-fvisibility=hidden", + "-Wformat=2", + "-Wfloat-equal", + "-Wdate-time", + ] + + configs = [ ":g_mem_dfx_config" ] + + deps = [ + "//utils/native/base:utils", + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara" + ] + + external_deps = [ + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "hiviewdfx_hilog_native:libhilog", + "faultloggerd:lib_dfx_dump_catcher", + ] + + subsystem_name = "multimedia" + part_name = "multimedia_media_standard" +} \ No newline at end of file diff --git a/glib/gmem.c b/glib/gmem.c index 605eac1ff175ebf8c8eea85fe350227185b18072..2e47236a7dc8e3964a5501134a421edffb851e99 100644 --- a/glib/gmem.c +++ b/glib/gmem.c @@ -40,6 +40,18 @@ #include "gthread.h" #include "glib_trace.h" +#include "gmemdfx.h" + +#if defined(G_MEM_DFX) + +#define DFX_TRACE(probe) probe + +#else + +#define DFX_TRACE(probe) + +#endif + /* notes on macros: * having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and * g_mem_profile(). @@ -104,6 +116,7 @@ g_malloc (gsize n_bytes) gpointer mem; mem = malloc (n_bytes); + DFX_TRACE(gMemAllocDfx((void *)mem, (unsigned int)n_bytes)); TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0)); if (mem) return mem; @@ -134,6 +147,7 @@ g_malloc0 (gsize n_bytes) gpointer mem; mem = calloc (1, n_bytes); + DFX_TRACE(gMemAllocDfx((void *)mem, (unsigned int)n_bytes)); TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0)); if (mem) return mem; @@ -169,6 +183,7 @@ g_realloc (gpointer mem, if (G_LIKELY (n_bytes)) { newmem = realloc (mem, n_bytes); + DFX_TRACE(gMemReallocDfx((void *)newmem, (void *)mem, (unsigned int)n_bytes)); TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 0)); if (newmem) return newmem; @@ -197,6 +212,7 @@ void g_free (gpointer mem) { free (mem); + DFX_TRACE(gMemFreeDfx((void *)mem)); TRACE(GLIB_MEM_FREE((void*) mem)); } diff --git a/glibmemdfx/gmemdfx.cpp b/glibmemdfx/gmemdfx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cfbeb53db7a1f325986849b1272df70581c5ef1a --- /dev/null +++ b/glibmemdfx/gmemdfx.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2022 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 "gmemdfx.h" +#include +#include +#include "gmemdfxdump.h" +#include "dfx_dump_catcher.h" +#include "param_wrapper.h" +#include "string_ex.h" + +#undef LOG_DOMAIN +#define LOG_DOMAIN 0xD002B00 + +#define __LOG(func, fmt, args...) \ + do { \ + (void)func(LABEL, "{%{public}s():%{public}d} " fmt, __FUNCTION__, __LINE__, ##args); \ + } while (0) + +#define LOGE(fmt, ...) __LOG(::OHOS::HiviewDFX::HiLog::Error, fmt, ##__VA_ARGS__) + +#define POINTER_MASK 0x00FFFFFF +#define FAKE_POINTER(addr) (POINTER_MASK & reinterpret_cast(addr)) + +struct memInfo { + uint64_t count = 0; + uint64_t size = 0; + std::string str; +}; + +namespace { + constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVGlibMemDfx"}; + static std::unordered_map memMap; + static uint64_t memCount = 0; + static std::mutex mutex; + static bool enableDump = false; + static unsigned int dumpSize = 0; +} + +void gMemAllocDfx(void *mem, unsigned int size) +{ + std::lock_guard lock(mutex); + if (mem == nullptr) { + return; + } + if (memMap.find(mem) != memMap.end()) { + LOGE("the mem 0x%{public}06" PRIXPTR " is already allocated", FAKE_POINTER(mem)); + return; + } + std::string str; + if (enableDump && size == dumpSize) { + OHOS::HiviewDFX::DfxDumpCatcher dumpLog; + bool ret = dumpLog.DumpCatch(getpid(), gettid(), str); + if (!ret) { + LOGE("dump error"); + } + } + + memMap[mem] = {memCount++, size, str}; +} + +void gMemReallocDfx(void *newMem, void *mem, unsigned int size) +{ + std::lock_guard lock(mutex); + if (mem != nullptr && memMap.erase(mem) == 0) { + LOGE("the mem 0x%{public}06" PRIXPTR " is already free", FAKE_POINTER(mem)); + } + if (memMap.find(newMem) != memMap.end()) { + LOGE("the mem 0x%{public}06" PRIXPTR " is already allocated", FAKE_POINTER(newMem)); + return; + } + std::string str; + if (enableDump && size == dumpSize) { + OHOS::HiviewDFX::DfxDumpCatcher dumpLog; + bool ret = dumpLog.DumpCatch(getpid(), gettid(), str); + if (!ret) { + LOGE("dump error"); + } + } + memMap[newMem] = {memCount++, size, str}; +} + +void gMemFreeDfx(void *mem) +{ + std::lock_guard lock(mutex); + if (mem != nullptr && memMap.erase(mem) == 0) { + LOGE("the mem 0x%{public}06" PRIXPTR " is already free", FAKE_POINTER(mem)); + } +} + +void getGMemDump(std::string &str) +{ + std::unordered_map memMapCopy; + { + std::lock_guard lock(mutex); + std::string dumpSizeStr; + int32_t size; + int32_t res = OHOS::system::GetStringParameter("sys.media.dump.mem.size", dumpSizeStr, ""); + if (res == 0 && !dumpSizeStr.empty()) { + OHOS::StrToInt(dumpSizeStr, size); + dumpSize = size; + enableDump = dumpSize == 0 ? false :true; + } else { + enableDump = false; + } + memMapCopy = memMap; + } + std::vector> memInfoVec(memMapCopy.begin(), memMapCopy.end()); + std::sort(memInfoVec.begin(), memInfoVec.end(), [&](auto &left, auto &right) { + return left.second.count < right.second.count; + }); + for (auto iter = memInfoVec.begin(); iter != memInfoVec.end(); iter++) { + str += "count:"; + str += std::to_string(iter->second.count) + ";"; + str += "size:"; + str += std::to_string(iter->second.size) + "\n"; + str += iter->second.str + "\n"; + } +} diff --git a/glibmemdfx/gmemdfx.h b/glibmemdfx/gmemdfx.h new file mode 100644 index 0000000000000000000000000000000000000000..5031973b7ca73c5be524c84f2d1702dae6d065f8 --- /dev/null +++ b/glibmemdfx/gmemdfx.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 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 G_MEM_DFX_H +#define G_MEM_DFX_H + +#ifdef __cplusplus +extern "C" { +#endif + +void __attribute__((visibility("default"))) gMemAllocDfx(void *mem, unsigned int size); +void __attribute__((visibility("default"))) gMemReallocDfx(void *newMem, void *mem, unsigned int size); +void __attribute__((visibility("default"))) gMemFreeDfx(void *mem); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/glibmemdfx/gmemdfxdump.h b/glibmemdfx/gmemdfxdump.h new file mode 100644 index 0000000000000000000000000000000000000000..3bb4ac376d6be4206edef5b295793940d21b51f5 --- /dev/null +++ b/glibmemdfx/gmemdfxdump.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 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 G_MEM_DFX_DUMP_H +#define G_MEM_DFX_DUMP_H + +#include + +void __attribute__((visibility("default"))) getGMemDump(std::string &str); + +#endif