| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 _WIN32 |
| #include <execinfo.h> |
| #endif |
| #include <string.h> |
| |
| #include <iostream> |
| |
| #include "../../../cmake-build-debug/include/common/error_info/error_info.h" |
| #include "alloc_base.h" |
| #include "common/logger/elog.h" |
| #include "stdio.h" |
| #include "stdlib.h" |
| #include "utils/util_define.h" |
| |
| namespace common { |
| |
| const char *g_mod_names[__LAST_MOD_ID] = { |
| /* 0 */ "DEFAULT", |
| /* 1 */ "MEMTABLE", |
| /* 2 */ "SCHEMA", |
| /* 3 */ "SQL", |
| /* 4 */ "NET", |
| /* 5 */ "NET_DATA", |
| /* 6 */ "TVLIST_DATA", |
| /* 7 */ "TVLIST_OBJ", |
| /* 8 */ "TSBLOCK", |
| /* 9 */ "CONTAINER", |
| /* 10 */ "TSSTORE_OBJ", |
| /* 11 */ "FLUSH_TASK_OBJ", |
| /* 12 */ "PAGE_WRITER_OUTPUT_STREAM", |
| /* 13 */ "CW_PAGES_DATA", |
| /* 14 */ "CHUNK_WRITER_OBJ", |
| /* 15 */ "STATISTIC_OBJ", |
| /* 16 */ "ENCODER_OBJ", |
| /* 17 */ "DECODER_OBJ", |
| /* 18 */ "TSFILE_WRITER_META", |
| /* 19 */ "TSFILE_WRITE_STREAM", |
| /* 20 */ "TIMESERIES_INDEX_OBJ", |
| /* 21 */ "BLOOM_FILTER", |
| /* 22 */ "OPEN_FILE_OBJ", |
| /* 23 */ "TSFILE_READER", |
| /* 24 */ "CHUNK_READER", |
| /* 25 */ "COMPRESSOR_OBJ", |
| /* 26 */ "ARRAY", |
| /* 27 */ "HASH_TABLE", |
| }; |
| |
| constexpr uint32_t HEADER_SIZE_4B = 4; |
| constexpr uint32_t HEADER_SIZE_8B = 8; |
| |
| void *mem_alloc(const size_t size, const AllocModID mid) { |
| // use 7bit at most |
| ASSERT(mid <= 127); |
| |
| if (size <= 0xFFFFFF) { |
| // use 3B size + 1B mod |
| auto *p = static_cast<char *>(malloc(size + HEADER_SIZE_4B)); |
| if (UNLIKELY(p == nullptr)) { |
| return nullptr; |
| } else { |
| uint32_t header = (size << 8) | static_cast<uint32_t>(mid); |
| *reinterpret_cast<uint32_t *>(p) = header; |
| return p + HEADER_SIZE_4B; |
| } |
| } else { |
| if (size > UINT32_MAX - HEADER_SIZE_4B) { |
| SET_ERR(error_info::E_OOM, "Too large spec to allocate"); |
| return nullptr; |
| } |
| auto *p = static_cast<char *>(malloc(size + HEADER_SIZE_8B)); |
| if (UNLIKELY(p == nullptr)) { |
| SET_ERR(error_info::E_OOM, "allocate failed"); |
| return nullptr; |
| } else { |
| const uint64_t large_size = size; |
| const uint64_t header = |
| ((large_size) << 8) | (static_cast<uint32_t>(mid) | (0x80)); |
| const auto low4b = static_cast<uint32_t>(header & 0xFFFFFFFF); |
| const auto high4b = static_cast<uint32_t>(header >> 32); |
| *reinterpret_cast<uint32_t *>(p) = high4b; |
| *reinterpret_cast<uint32_t *>(p + 4) = low4b; |
| return p + HEADER_SIZE_8B; |
| } |
| } |
| } |
| |
| #ifndef _WIN32 |
| void printCallers() { |
| int layers = 0, i = 0; |
| char **symbols = nullptr; |
| |
| const int64_t MAX_FRAMES = 32; |
| |
| void *frames[MAX_FRAMES]; |
| memset(frames, 0, sizeof(frames)); |
| layers = backtrace(frames, MAX_FRAMES); |
| for (i = 0; i < layers; i++) { |
| printf("Layer %d: %p\n", i, frames[i]); |
| } |
| printf("------------------\n"); |
| |
| symbols = backtrace_symbols(frames, layers); |
| if (symbols) { |
| for (i = 0; i < layers; i++) { |
| printf("SYMBOL layer %d: %s\n", i, symbols[i]); |
| } |
| free(symbols); |
| } else { |
| printf("Failed to parse function names\n"); |
| } |
| } |
| #endif |
| |
| void mem_free(void *ptr) { |
| // try as 4Byte header |
| char *p = static_cast<char *>(ptr); |
| uint32_t header = *reinterpret_cast<uint32_t *>(p - HEADER_SIZE_4B); |
| if ((header & 0x80) == 0) { |
| // 4Byte header |
| // uint32_t size = header >> 8; |
| // AllocModID mid = (AllocModID)(header & 0x7F); |
| // // ModStat::get_instance().update_free(mid, size); |
| ::free(p - HEADER_SIZE_4B); |
| } else { |
| // 8Byte header |
| uint64_t header8b = static_cast<uint64_t>(*reinterpret_cast<uint32_t *>(p - 4)) | |
| (static_cast<uint64_t>(*reinterpret_cast<uint32_t *>(p - 8)) << 32); |
| // AllocModID mid = (AllocModID)(header8b & 0x7F); |
| // uint32_t size = (uint32_t)(header8b >> 8); |
| // ModStat::get_instance().update_free(mid, size); |
| ::free(p - HEADER_SIZE_8B); |
| } |
| } |
| |
| void *mem_realloc(void *ptr, uint32_t size) { |
| AllocModID mid_org; |
| uint32_t size_org; |
| char *p = (char *)ptr; |
| uint32_t header_org = |
| *(uint32_t *)(p - HEADER_SIZE_4B); // try as 4Byte header |
| if ((header_org & 0x80) == 0) { |
| // header_org is 4byte |
| size_org = header_org >> 8; |
| mid_org = (AllocModID)(header_org & 0x7F); |
| if (size <= 0xFFFFFF) { |
| p = (char *)realloc(p - HEADER_SIZE_4B, size + HEADER_SIZE_4B); |
| if (UNLIKELY(p == nullptr)) { |
| return nullptr; |
| } else { |
| uint32_t header = |
| (size << 8) | ((uint32_t)mid_org); // size changed |
| *((uint32_t *)p) = header; |
| ModStat::get_instance().update_alloc( |
| mid_org, int32_t(size) - int32_t(size_org)); |
| return p + HEADER_SIZE_4B; |
| } |
| } else { // size > 0xFFFFFF, realloc(os_p, size + header_len) |
| p = (char *)realloc(p - HEADER_SIZE_4B, size + HEADER_SIZE_8B); |
| if (UNLIKELY(p == nullptr)) { |
| return nullptr; |
| } else { |
| std::memmove(p + HEADER_SIZE_8B, p + HEADER_SIZE_4B, size_org); |
| // reconstruct 8-byte header |
| uint64_t large_size = size; |
| uint64_t header = |
| ((large_size) << 8) | (((uint32_t)mid_org) | (0x80)); |
| uint32_t low4b = (uint32_t)(header & 0xFFFFFFFF); |
| uint32_t high4b = (uint32_t)(header >> 32); |
| *(uint32_t *)p = high4b; |
| *(uint32_t *)(p + 4) = low4b; |
| ModStat::get_instance().update_alloc( |
| mid_org, int32_t(size) - int32_t(size_org)); |
| return p + HEADER_SIZE_8B; |
| } |
| } |
| } else { // header_org is 8byte |
| uint64_t header = |
| ((uint64_t)(*(uint32_t *)(p - 4))) | |
| ((uint64_t)(*(uint32_t *)(p - 8)) << 32); // 8Byte header |
| mid_org = (AllocModID)(header & 0x7F); |
| size_org = (uint32_t)(header >> 8); |
| if (size <= 0xFFFFFF) { |
| uint32_t save_data = |
| *(uint32_t *)(p - HEADER_SIZE_8B + HEADER_SIZE_4B + size); |
| p = (char *)realloc(p - HEADER_SIZE_8B, size + HEADER_SIZE_4B); |
| if (UNLIKELY(p == nullptr)) { |
| return nullptr; |
| } else { |
| std::memmove(p + HEADER_SIZE_4B, p + HEADER_SIZE_8B, |
| size - HEADER_SIZE_4B); |
| // reconstruct 4-byte header |
| uint32_t header4b = (size << 8) | (((uint32_t)mid_org)); |
| *((uint32_t *)p) = header4b; |
| // reconstruct data |
| *(uint32_t *)((char *)p + size - 4) = save_data; |
| ModStat::get_instance().update_alloc( |
| mid_org, int32_t(size) - int32_t(size_org)); |
| return p + HEADER_SIZE_4B; |
| } |
| } else { |
| p = (char *)realloc(p - HEADER_SIZE_8B, size + HEADER_SIZE_8B); |
| if (UNLIKELY(p == nullptr)) { |
| return nullptr; |
| } else { |
| uint64_t large_size = size; |
| uint64_t header8b = |
| ((large_size) << 8) | (((uint32_t)mid_org) | (0x80)); |
| uint32_t low4b = (uint32_t)(header8b & 0xFFFFFFFF); |
| uint32_t high4b = (uint32_t)(header8b >> 32); |
| *(uint32_t *)p = high4b; |
| *(uint32_t *)(p + 4) = low4b; |
| ModStat::get_instance().update_alloc( |
| mid_org, int32_t(size) - int32_t(size_org)); |
| return p + HEADER_SIZE_8B; |
| } |
| } |
| } |
| } |
| |
| void ModStat::init() { |
| stat_arr_ = (int32_t *)(::malloc(ITEM_SIZE * ITEM_COUNT)); |
| for (int8_t i = 0; i < __LAST_MOD_ID; i++) { |
| int32_t *item = get_item(i); |
| *item = 0; |
| } |
| } |
| |
| void ModStat::destroy() { ::free(stat_arr_); } |
| |
| |
| BaseAllocator g_base_allocator; |
| |
| } // end namespace common |