[CP] support alloc_align/free_align for ObIAllocator

This commit is contained in:
tushicheng
2024-07-25 12:54:19 +00:00
committed by ob-robot
parent 7cc412c2ba
commit cb77423ea8
6 changed files with 69 additions and 58 deletions

View File

@ -21,6 +21,45 @@ namespace oceanbase
namespace common
{
using lib::ObMemAttr;
class ObAllocAlign
{
public:
struct Header
{
static const uint32_t MAGIC_CODE = 0XAA22CCE1;
bool check_magic_code() const { return MAGIC_CODE == magic_code_; }
void mark_unused() { magic_code_ &= ~0x1; }
uint32_t magic_code_;
uint32_t offset_;
};
template<typename alloc_func, typename... Args>
static void *alloc_align(const int64_t size, const int64_t align, alloc_func &&alloc, const Args&... args)
{
void *ptr = NULL;
int64_t real_align = lib::align_up2(align, 16);
int64_t real_size = real_align + size + sizeof(Header);
char *tmp_ptr = (char*)alloc(real_size, args...);
if (NULL != tmp_ptr) {
ptr = (void*)lib::align_up2((int64_t)tmp_ptr + sizeof(Header), real_align);
Header *header = (Header*)ptr - 1;
header->magic_code_ = Header::MAGIC_CODE;
header->offset_ = (char*)header - tmp_ptr;
}
return ptr;
}
template<typename free_func>
static void free_align(void *ptr, free_func &&free)
{
if (NULL != ptr) {
Header *header = (Header*)ptr - 1;
abort_unless(header->check_magic_code());
header->mark_unused();
char *orig_ptr = (char*)header - header->offset_;
free(orig_ptr);
}
}
};
class ObIAllocator
{
public:
@ -46,6 +85,20 @@ public:
return nullptr;
}
virtual void free(void *ptr) = 0;
virtual void *alloc_align(const int64_t size, const int64_t align) final
{
return ObAllocAlign::alloc_align(size, align,
[this](const int64_t size) { return this->alloc(size); });
}
virtual void *alloc_align(const int64_t size, const int64_t align, const ObMemAttr &attr) final
{
return ObAllocAlign::alloc_align(size, align,
[this](const int64_t size, const ObMemAttr &attr) { return this->alloc(size, attr); }, attr);
}
virtual void free_align(void *ptr) final
{
ObAllocAlign::free_align(ptr, [this](void *ptr){ this->free(ptr); });
}
virtual int64_t total() const
{
return 0;

View File

@ -60,15 +60,6 @@ public:
{
return alloc(size);
}
void *alloc_align(const int64_t size, const int64_t align)
{
UNUSED(align);
return alloc(size);
}
virtual void *alloc_align(const int64_t size, const int64_t align, const ObMemAttr &)
{
return alloc_align(size, align);
}
virtual void free(void *ptr) override;
void set_label(const lib::ObLabel &label) { UNUSED(label); }

View File

@ -276,16 +276,16 @@ bool ObFIFOAllocator::check_magic(void *p, int64_t &size)
void *ObFIFOAllocator::alloc(const int64_t size)
{
return alloc_align(size, 16);
return inner_alloc_align(size, 16);
}
void *ObFIFOAllocator::alloc(const int64_t size, const ObMemAttr &attr)
{
UNUSED(attr);
return alloc_align(size, 16);
return inner_alloc_align(size, 16);
}
void *ObFIFOAllocator::alloc_align(const int64_t size, const int64_t align)
void *ObFIFOAllocator::inner_alloc_align(const int64_t size, const int64_t align)
{
ObLockGuard<ObSpinLock> guard(lock_);
void *ptr = nullptr;

View File

@ -97,7 +97,6 @@ public:
void reset();
void *alloc(const int64_t size);
void *alloc(const int64_t size, const ObMemAttr &attr);
virtual void *alloc_align(const int64_t size, const int64_t align);
void free(void *p);
void set_label(const lib::ObLabel &label) { attr_.label_ = label; }
void set_attr(const ObMemAttr &attr) { attr_ = attr; }
@ -129,6 +128,7 @@ public:
}
private:
void *inner_alloc_align(const int64_t size, const int64_t align);
BasePageHeader *get_page_header(void *p);
bool check_param(const int64_t size, const int64_t align);
bool check_magic(void *p, int64_t &size);

View File

@ -61,55 +61,13 @@ void *oceanbase::common::ob_malloc_align(const int64_t alignment, const int64_t
void *oceanbase::common::ob_malloc_align(const int64_t align, const int64_t nbyte,
const ObMemAttr &attr)
{
const int min_align = 16;
const int64_t alignment =
align <= min_align ? min_align : lib::align_up2(align, 16);
char *ptr = static_cast<char *>(oceanbase::common::ob_malloc(nbyte + alignment, attr));
char *align_ptr = NULL;
if (NULL != ptr) {
align_ptr = reinterpret_cast<char *>(oceanbase::common::upper_align(reinterpret_cast<int64_t>(ptr),
alignment));
if (align_ptr == ptr) {
align_ptr = ptr + alignment;
}
int64_t padding = align_ptr - ptr;
if (!(padding <= alignment && padding > 0)) {
_OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "invalid padding(padding=%ld, alignment=%ld", padding, alignment);
}
uint8_t *sign_ptr = reinterpret_cast<uint8_t *>(align_ptr - 1);
int64_t *header_ptr = reinterpret_cast<int64_t *>(align_ptr - 1 - sizeof(int64_t));
if (padding < (int64_t)sizeof(int64_t) + 1) {
*sign_ptr = static_cast<uint8_t>(padding) & 0x7f;
} else {
*sign_ptr = 0x80;
*header_ptr = padding;
}
} else {
_OB_LOG_RET(WARN, OB_ALLOCATE_MEMORY_FAILED, "ob_tc_malloc allocate memory failed, alignment[%ld], nbyte[%ld], tenant_id[%lu], label[%s].",
alignment, nbyte, attr.tenant_id_, (const char*)attr.label_);
}
return align_ptr;
return ObAllocAlign::alloc_align(nbyte, align,
[](const int64_t size, const ObMemAttr &attr){ return ob_malloc(size, attr); }, attr);
}
void oceanbase::common::ob_free_align(void *ptr)
{
if (NULL == ptr) {
_OB_LOG_RET(WARN, OB_INVALID_ARGUMENT, "cannot free NULL pointer.");
} else if (oceanbase::lib::ObMallocAllocator::is_inited_) {
uint8_t *sign_ptr = reinterpret_cast<uint8_t *>(static_cast<char *>(ptr) - 1);
int64_t *header_ptr = reinterpret_cast<int64_t *>(static_cast<char *>(ptr) - 1 - sizeof(int64_t));
char *origin_ptr = NULL;
if (NULL != sign_ptr) {
if ((*sign_ptr & 0x80) != 0) {
origin_ptr = reinterpret_cast<char *>(ptr) - (*header_ptr);
} else {
origin_ptr = reinterpret_cast<char *>(ptr) - (*sign_ptr & 0x7f);
}
if (NULL != origin_ptr) {
oceanbase::common::ob_free(origin_ptr);
}
}
}
ObAllocAlign::free_align(ptr, [](void *ptr){ ob_free(ptr); });
}

View File

@ -91,6 +91,15 @@ TEST_F(TestAllocator, basic)
sz = ((sz | reinterpret_cast<size_t>(p[0])) & ((1<<13) - 1));
}
// test alloc_align/free_align
for (int i = 0; i < 10; ++i) {
int64_t align = 8<<i;
void *ptr = a.alloc_align(100, align);
ASSERT_EQ(0, (int64_t)ptr & (align - 1));
ASSERT_GT(a.used(), 0);
a.free_align(ptr);
ASSERT_EQ(a.used(), 0);
}
cout << "done" << endl;
}