159 lines
4.3 KiB
C
159 lines
4.3 KiB
C
#include "memctl.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
|
|
#define container_of(ptr, type, member) \
|
|
((type *)((char *)(ptr) - offsetof(type, member)))
|
|
|
|
int extend_pool(mem_ctl* self,int size)
|
|
{
|
|
if(self == NULL)//入参检查
|
|
{
|
|
return -1;
|
|
}
|
|
int poolsize = atomic_load(&self->poolsize);
|
|
int target = poolsize +size;//计算目标大小
|
|
if(target >MAX_MEM_SIZE)
|
|
target = MAX_MEM_SIZE;//计算限制
|
|
|
|
for(int i = poolsize;i<target;i++)//分配内存
|
|
{
|
|
if(self->blocks[i].location !=NULL)//若存在未释放内存
|
|
free(self->blocks[i].location);
|
|
self->blocks[i].location = malloc(MEM_BLOCK_SIZE);
|
|
if(self->blocks[i].location == NULL)
|
|
return target-i;//堆内存不足
|
|
atomic_store(&self->blocks[i].condition,MEM_FREE);
|
|
}
|
|
atomic_fetch_add(&self->poolsize,size);
|
|
int log = atomic_load(&self->logbuf)+size/2;
|
|
atomic_store(&self->logbuf,log);//重新划定日志区
|
|
return 0;
|
|
}
|
|
|
|
void **GetBlock(mem_ctl* self,int type)
|
|
{
|
|
int status = 0;
|
|
int sp=0,start = 0;
|
|
int id;
|
|
//模式判断
|
|
if(type == LOGMOD)
|
|
{
|
|
id = atomic_load(&self->Loglast_loc);
|
|
sp = atomic_load(&self->poolsize);
|
|
start = atomic_load(&self->logbuf);
|
|
if(id<start)
|
|
id = start;
|
|
}
|
|
else
|
|
{
|
|
id = atomic_load(&self->Commenlast_loc);
|
|
sp = atomic_load(&self->logbuf)+1;
|
|
if(id>sp)
|
|
id = start;
|
|
}
|
|
int i = id;
|
|
for(status;status<CYCLE_NUM;status++)//最多扫描轮次
|
|
{
|
|
//获取空闲块
|
|
for(i;i<sp;i++)
|
|
{
|
|
if(atomic_fetch_sub(&self->blocks[i].condition,1) == MEM_FREE)
|
|
{
|
|
atomic_fetch_sub(&self->blocks[i].condition,1);
|
|
if(i>self->logbuf)
|
|
atomic_store(&self->Loglast_loc,i);
|
|
else
|
|
atomic_store(&self->Commenlast_loc,i);
|
|
return &self->blocks[i].location;
|
|
}
|
|
else{
|
|
atomic_fetch_add(&self->blocks[i].condition,1);//回滚路径
|
|
}
|
|
}
|
|
i = start;
|
|
atomic_fetch_add(&self->mem_e_indicator,1);
|
|
//检查是否需要扩池
|
|
if(atomic_fetch_sub(&self->mem_e_indicator,POOL_EXPEND_ID)>POOL_EXPEND_ID)
|
|
{
|
|
extend_pool(self,POOL_EXPEND_SIZE);
|
|
}
|
|
else{
|
|
atomic_fetch_add(&self->mem_e_indicator,POOL_EXPEND_ID);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int FreeBlock(mem_ctl* self,void** block_p)
|
|
{
|
|
mem_block *block;
|
|
block = container_of(block_p,mem_block,location);
|
|
if(self == NULL)
|
|
return -1;
|
|
if(block == NULL)
|
|
return -1;
|
|
if(block < &self->blocks[COMINE_MEM_SIZE])//标准池部分归还
|
|
{
|
|
atomic_fetch_add(&block->condition,2);
|
|
block = NULL;
|
|
return 0;
|
|
}
|
|
else//扩容池尝试回收
|
|
{
|
|
atomic_fetch_add(&block->condition,1);
|
|
free(block->location);
|
|
block->location = NULL;
|
|
int poolsize = atomic_load(&self->poolsize);
|
|
if(&self->blocks[poolsize-1] == block)
|
|
{
|
|
for(int i = poolsize -1;i>COMINE_MEM_SIZE;i--)
|
|
{
|
|
if(atomic_load(&self->blocks[i].condition) == PROCESSING)
|
|
{
|
|
poolsize--;
|
|
}
|
|
else{
|
|
break;
|
|
}
|
|
if(poolsize-COMINE_MEM_SIZE%2 == 0)
|
|
{
|
|
atomic_fetch_sub(&self->logbuf,1);
|
|
}
|
|
}
|
|
}
|
|
atomic_store(&self->poolsize,poolsize);
|
|
}
|
|
}
|
|
|
|
int init_memctl(mem_ctl *self)
|
|
{
|
|
if(self == NULL)
|
|
return -1;
|
|
self->poolsize = 0;
|
|
for(int i =0;i<MAX_MEM_SIZE;i++)
|
|
{
|
|
self->blocks[i].location = NULL;
|
|
atomic_init(&self->blocks[i].condition,PROCESSING);//初始化池
|
|
}
|
|
extend_pool(self,COMINE_MEM_SIZE);//预分配内存
|
|
self->Commenlast_loc = 0;
|
|
self->logbuf = COMINE_MEM_SIZE/2;
|
|
self->mem_e_indicator = 0;
|
|
self->FreeBlock = FreeBlock;
|
|
self->GetBlock = GetBlock;
|
|
return 0;
|
|
}
|
|
|
|
int free_memctl(mem_ctl *self)//清除内存池
|
|
{
|
|
if(self == NULL)
|
|
return -1;
|
|
for(int i = 0;i<MAX_MEM_SIZE;i++)
|
|
{
|
|
if(self->blocks[i].location!=NULL)
|
|
free(self->blocks[i].location);
|
|
}
|
|
return 0;
|
|
} |