* Copyright (c) 2022 Huawei Technologies Co.,Ltd.
*
* CBB is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* cm_memory.h
*
*
* IDENTIFICATION
* src/cm_utils/cm_memory.h
*
* -------------------------------------------------------------------------
*/
#ifndef __CM_MEMORY_H__
#define __CM_MEMORY_H__
#include "cm_defs.h"
#include "cm_text.h"
#include "cm_sync.h"
#include "cm_spinlock.h"
#ifndef WIN32
#include <sys/mman.h>
#include <execinfo.h>
#include <pthread.h>
#endif
#include "cm_bilist.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WIN32
#ifdef _WIN64
#define CM_MFENCE \
{ \
_mm_mfence(); \
}
#else
#define CM_MFENCE \
{ \
__asm {mfence } \
}
#endif
#elif defined(__arm__) || defined(__aarch64__)
#define CM_MFENCE \
{ \
__asm__ volatile("dmb ish" :: \
: "memory"); \
}
#elif defined(__i386__) || defined(__x86_64__)
#define CM_MFENCE \
{ \
__asm__ volatile("mfence" :: \
: "memory"); \
}
#elif defined(__loongarch__)
#define CM_MFENCE \
{ \
__asm__ volatile("" :: \
: "memory"); \
}
#endif
typedef struct st_mem_block {
struct st_mem_zone *mem_zone;
uint64 size;
uint64 actual_size;
uint64 bitmap;
bilist_node_t link;
bool8 use_flag;
bool8 reserved[3];
uint32 padding;
CM_MAGIC_DECLARE
char data[4];
} mem_block_t;
#define MEM_BLOCK_LEFT 0
#define MEM_BLOCK_RIGHT 1
#define MEM_BLOCK_SIZE (OFFSET_OF(mem_block_t, data))
#define mem_block_t_MAGIC 8116518
#define mem_zone_t_MAGIC 8116517
#define mem_pool_t_MAGIC 8116519
#define mem_context_block_t_MAGIC 8116520
#define ddes_buffer_head_t_MAGIC 8116521
#define MEM_NUM_FREELISTS 26
typedef struct st_mem_zone {
struct st_mem_pool *mem;
uint64 total_size;
uint64 used_size;
bilist_node_t link;
union {
bilist_t list[MEM_NUM_FREELISTS];
struct {
bilist_t list_64;
bilist_t list_128;
bilist_t list_256;
bilist_t list_512;
bilist_t list_1k;
bilist_t list_2k;
bilist_t list_4k;
bilist_t list_8k;
bilist_t list_16k;
bilist_t list_32k;
bilist_t list_64k;
bilist_t list_128k;
bilist_t list_256k;
bilist_t list_512k;
bilist_t list_1m;
bilist_t list_2m;
bilist_t list_4m;
bilist_t list_8m;
bilist_t list_16m;
bilist_t list_32m;
bilist_t list_64m;
bilist_t list_128m;
bilist_t list_256m;
bilist_t list_512m;
bilist_t list_1g;
bilist_t list_2g;
};
};
CM_MAGIC_DECLARE
} mem_zone_t;
typedef struct st_memory_context memory_context_t;
typedef void *(*ddes_malloc_proc_t)(memory_context_t* context, uint64 size);
typedef void (*ddes_free_proc_t)(void *ptr);
typedef struct st_ddes_memory_allocator {
memory_context_t* context;
ddes_malloc_proc_t malloc_proc;
ddes_free_proc_t free_proc;
} ddes_memory_allocator_t;
typedef struct st_mem_pool {
char name[CM_NAME_BUFFER_SIZE];
uint64 total_size;
uint64 max_size;
uint64 used_size;
spinlock_t lock;
cm_event_t event;
bilist_t mem_zone_lst;
ddes_memory_allocator_t mem_allocator;
CM_MAGIC_DECLARE
} mem_pool_t;
typedef struct st_mem_context_block {
struct st_mem_context_block *next;
struct st_mem_context_block *prev;
uint64 size;
CM_MAGIC_DECLARE
} mem_context_block_t;
typedef struct st_ddes_buffer_head {
memory_context_t* context;
uint64 size;
uint64 offset;
CM_MAGIC_DECLARE
} ddes_buffer_head_t;
typedef struct st_memory_context {
spinlock_t lock;
char name[CM_NAME_BUFFER_SIZE];
memory_context_t* parent;
memory_context_t* firstchild;
memory_context_t* nextchild;
memory_context_t* prechild;
uint64 mem_max_size;
int64 allocated_size;
int64 used_size;
bool8 is_init;
mem_context_block_t* blocks;
cm_memory_allocator_t mem_allocator;
} memory_context_t;
void *buddy_pool_malloc_prot(memory_context_t *context, uint64 size);
void buddy_pool_free_prot(void *pointer);
status_t buddy_pool_init(char *pool_name, uint64 init_size, uint64 max_size, mem_pool_t *mem);
status_t buddy_pool_init_ext(char *pool_name, uint64 init_size, uint64 max_size, mem_pool_t *mem,
ddes_memory_allocator_t* mem_allocator);
status_t buddy_pool_set_mem_allocator(mem_pool_t *mem, ddes_memory_allocator_t *mem_allocator);
void *galloc(uint64 size, mem_pool_t *mem);
void *galloc_timeout(uint64 size, mem_pool_t *mem, uint32 timeout_ms);
void *grealloc(void *p, uint64 size, mem_pool_t *mem);
void gfree(void *p);
void buddy_pool_deinit(mem_pool_t *mem);
memory_context_t *ddes_memory_context_create(memory_context_t *parent, uint64 max_size, char *name,
cm_memory_allocator_t *mem_allocator);
void ddes_memory_context_destroy(memory_context_t *context);
void *ddes_alloc(memory_context_t *context, uint64 size);
void *ddes_alloc_align(memory_context_t *context, uint32 alignment, uint64 size);
void ddes_free(void *ptr);
static inline void ddes_memory_stat(memory_context_t *context, uint64 *used, uint64 *total)
{
*used = (uint64)context->used_size;
*total = context->mem_max_size;
}
static inline uint64 mem_used_size(const mem_pool_t *mem)
{
return mem->used_size;
}
static inline uint64 mem_used_threshold(const mem_pool_t *mem)
{
return (3 * mem->max_size / 4);
}
static inline uint64 mem_max_size(const mem_pool_t *mem)
{
return mem->max_size;
}
extern mem_pool_t g_buddy_pool;
typedef struct st_memory_chunk_t {
char *addr;
uint64 total_size;
uint64 offset;
} memory_chunk_t;
static inline char *cm_alloc_memory_from_chunk(memory_chunk_t *mem_chunk, uint64 size)
{
char *curr_addr = mem_chunk->addr + mem_chunk->offset;
mem_chunk->offset += size;
cm_panic(mem_chunk->offset <= mem_chunk->total_size);
return curr_addr;
}
#ifdef __cplusplus
}
#endif
#endif