blob: 0bf846471ba4c3c1a6f5d202832e2e3347d37a9a [file] [log] [blame]
/*
* 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