From 0ece30dc7c0e34b4c5911969b8fa99c33c6d023c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 30 Nov 2022 17:48:47 +0300 Subject: Telegram: update for TDLIB --- .../Telegram/tdlib/td/memprof/memprof_stat.cpp | 166 +++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 protocols/Telegram/tdlib/td/memprof/memprof_stat.cpp (limited to 'protocols/Telegram/tdlib/td/memprof/memprof_stat.cpp') diff --git a/protocols/Telegram/tdlib/td/memprof/memprof_stat.cpp b/protocols/Telegram/tdlib/td/memprof/memprof_stat.cpp new file mode 100644 index 0000000000..00d371431e --- /dev/null +++ b/protocols/Telegram/tdlib/td/memprof/memprof_stat.cpp @@ -0,0 +1,166 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "memprof/memprof_stat.h" + +#include "td/utils/port/platform.h" + +#if (TD_DARWIN || TD_LINUX) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +bool is_memprof_on() { + return true; +} + +#define my_assert(f) \ + if (!(f)) { \ + std::abort(); \ + } + +struct malloc_info { + std::int32_t magic; + std::int32_t size; +}; + +static std::atomic total_memory_used; + +void register_xalloc(malloc_info *info, std::int32_t diff) { + my_assert(info->size >= 0); + // TODO: this is very slow in case of several threads. + // Currently this statistics is intended only for memory benchmarks. + total_memory_used.fetch_add(diff * info->size, std::memory_order_relaxed); +} + +std::size_t get_used_memory_size() { + return total_memory_used.load(); +} + +extern "C" { + +static constexpr std::size_t RESERVED_SIZE = 16; +static constexpr std::int32_t MALLOC_INFO_MAGIC = 0x27138373; + +static void *do_malloc(std::size_t size) { + static_assert(RESERVED_SIZE % alignof(std::max_align_t) == 0, "fail"); + static_assert(RESERVED_SIZE >= sizeof(malloc_info), "fail"); +#if TD_DARWIN + static void *malloc_void = dlsym(RTLD_NEXT, "malloc"); + static auto malloc_old = *reinterpret_cast(&malloc_void); +#else + extern decltype(malloc) __libc_malloc; + static auto malloc_old = __libc_malloc; +#endif + auto *info = static_cast(malloc_old(size + RESERVED_SIZE)); + auto *buf = reinterpret_cast(info); + + info->magic = MALLOC_INFO_MAGIC; + info->size = static_cast(size); + + register_xalloc(info, +1); + + void *data = buf + RESERVED_SIZE; + + return data; +} + +static malloc_info *get_info(void *data_void) { + auto *data = static_cast(data_void); + auto *buf = data - RESERVED_SIZE; + + auto *info = reinterpret_cast(buf); + my_assert(info->magic == MALLOC_INFO_MAGIC); + return info; +} + +void *malloc(std::size_t size) { + return do_malloc(size); +} + +void free(void *data_void) { + if (data_void == nullptr) { + return; + } + auto *info = get_info(data_void); + register_xalloc(info, -1); + +#if TD_DARWIN + static void *free_void = dlsym(RTLD_NEXT, "free"); + static auto free_old = *reinterpret_cast(&free_void); +#else + extern decltype(free) __libc_free; + static auto free_old = __libc_free; +#endif + return free_old(info); +} + +void *calloc(std::size_t size_a, std::size_t size_b) { + auto size = size_a * size_b; + void *res = do_malloc(size); + std::memset(res, 0, size); + return res; +} + +void *realloc(void *ptr, std::size_t size) { + if (ptr == nullptr) { + return do_malloc(size); + } + auto *info = get_info(ptr); + auto *new_ptr = do_malloc(size); + auto to_copy = std::min(static_cast(size), info->size); + std::memcpy(new_ptr, ptr, to_copy); + free(ptr); + return new_ptr; +} + +void *memalign(std::size_t alignment, std::size_t size) { + auto res = malloc(size); + my_assert(reinterpret_cast(res) % alignment == 0); + return res; +} + +int posix_memalign(void **memptr, size_t alignment, size_t size) { + auto res = malloc(size); + my_assert(reinterpret_cast(res) % alignment == 0); + *memptr = res; + return 0; +} +} + +// c++14 guarantees that it is enough to override these two operators. +void *operator new(std::size_t count) { + return do_malloc(count); +} +void operator delete(void *ptr) noexcept(true) { + free(ptr); +} +// because of gcc warning: the program should also define 'void operator delete(void*, std::size_t)' +void operator delete(void *ptr, std::size_t) noexcept(true) { + free(ptr); +} + +// c++17 +// void *operator new(std::size_t count, std::align_val_t al); +// void operator delete(void *ptr, std::align_val_t al); + +#else +bool is_memprof_on() { + return false; +} +std::size_t get_used_memory_size() { + return 0; +} +#endif -- cgit v1.2.3