📄 memmgr.c copy 2
字号:
#include "memmgr.h"#include <stdlib.h>mem_info *mem_init( void *start, int len, int block_size ){ mem_block *first; mem_info *mem; first = malloc( sizeof( *first )); if( first == NULL ) return NULL; first->base = start; first->size = len; first->prev = first->next = NULL; first->inuse = false; mem = malloc( sizeof( *mem )); if( mem == NULL ) { free( first ); return NULL; } mem->first = first; return mem;}void mem_destroy( mem_info *info ){ mem_block *cur, *next; for( cur = info->first; cur; cur = next ) { next = cur->next; free( cur ); } free( info );}mem_client_block *mem_alloc( mem_client_info *mem_client, int size ){ mem = mem_client->server_info; if( size == 0 ) { SHOW_ERROR0( 1, "tried to alloc block of size zero" ); return B_INVALID_PARAMS; } if( mem_client->free_list == NULL ) { SHOW_ERROR0( 1, "Out of client memory blocks" ); return B_ERROR; } num_blocks = (size + mem->block_size - 1) & ~(mem->block_size - 1); for( start = 0; start < mem->num_blocks; ) { for( left_len = num_blocks, cur_pos = start; len > 0; ) { if( cur_pos > mem->num_blocks ) break; cur_block = mem->blocks[cur_pos]; remaining_block_len = cur_block->len - (start - cur_block->start); if( cur_block->state != state_locked ) { cur_pos += remaining_block_len; len -= remaining_block_len; } else { cur_pos = start = cur_pos + remaining_block_len; len = num_blocks; } } if( len < num_blocks ) break; cur_costs = mem_calc_costs( start, len ); if( cur_costs < best_costs ) { best_start = start; best_costs = cur_costs; if( best_costs == 0 ) break; } cur_block = mem->blocks[start]; skip_head = cur_block->len - (start - cur_block->start); cur_block = mem->blocks[start + len - 1]; skip_tail = cur_block->len - (start + len - 1 - cur_block->start); /*if( skip_tail == 0 ) skip_tail = 1;*/ start += MAX( skip_head, skip_tail ); } if( best_start == 0 ) { SHOW_ERROR( 1, "Couldn't find gap of requested size (%i bytes)", size ); return B_NO_MEMORY; for( left_blocks = num_blocks, cur_pos = best_start; left_blocks > 0; ) { cur_block = mem->blocks[cur_pos]; remaining_block_len = cur_block->len - (start - cur_block->start); mem_free( mem, cur_block ); cur_pos += remaining_block_len; left_blocks -= remaining_block_len; } new_block = mem->block_array[best_start]; new_block->mem_client = mem_client; new_block->client = mem_client_info; new_block->start = best_start; new_block->len = num_blocks; new_block->state = state_inuse; new_block->address = mem_server->address + num_blocks * mem_server->block_size; client_block->server_block = new_block; client_block->discarded = false; for( left_blocks = num_blocks, cur_pos = best_start; left_blocks > 0; --left_blocks, ++cur_pos ) { mem->blocks[cur_pos] = new_block; } return B_OK; }void mem_discard( mem_server_block *server_block ){ mem_client = server_block->mem_client; client_block = server_block->client_block; client_block->discarded = true; client_block->next = mem_client->discarded_list; mem_client->discarded_list = client_block;} void mem_markfree( mem_server_info *mem_server, int pos, int len ){ server_block = client_block->server_block; free_block = mem_server->blocks[client_block->start]; free_block->start = start; free_block->len = len; if( start > 0 ) { prev_block = mem_server->blocks[start-1]; if( prev_block->state = state_free ) { prev_block->len += len; free_block = prev_block; } } for( cur_pos = server_block->start, blocks_left = server_block->len; blocks_left > 0; ++cur_pos, --blocks_left ) { mem_server->blocks[cur_pos] = free_block; }}void mem_remove_from_discarded( mem_client_info *mem_client, mem_client_block *client_block ){ if( cur_block == mem_client->discarded_list ) mem_client->discarded_list = cur_block->next; else { for( cur_block = mem_client->discarded_list; cur_block; cur_block = cur_block->next ) { if( cur_block->next == client_block ) break; } if( cur_block == NULL ) SHOW_ERROR( 0, "couldn't find discarded block in list" ); else cur_block->next = client_block->next; }} status_t mem_free( mem_client_info *mem_client, mem_client_block *client_block ){ mem_server_info *mem_server = mem_client->server_info; if( client_block->discarded ) mem_remove_from_discarded( mem_client, client_block ); mem_markfree( mem_server, server_block->start, server_block->len; client_block->next = mem_client->free_list; mem_client->free_list = client_block;} mem_block *cur, *new_entry; size = (size + mem->block_size - 1) & ~(mem->block_size - 1); for( cur = mem->first; cur; cur = cur->next ) { if( !cur->inuse && cur->size >= size ) break; } if( cur == NULL ) return NULL; cur->inuse = true; if( size == cur->size ) return cur; new_entry = malloc( sizeof( *new_entry )); if( new_entry == NULL ) return NULL; new_entry->base = cur->base; new_entry->size = size; cur->base += size; cur->size -= size; if( cur->prev ) cur->prev->next = new_entry; else mem->first = new_entry; cur->prev = new_entry; new_entry->next = cur; return new_entry;}void mem_free( mem_info *info, mem_block *block ){ mem_block *prev, *next; block->inuse = false; prev = block->prev; if( prev && !prev->inuse ) { prev->size += block->size; if( block->next ) block->next->prev = prev; prev->next = block->next; free( block ); block = prev; } next = block->next; if( next && !next->inuse ) { next->size += block->size; if( block->prev ) { block->prev->next = next; } else info->first = next; next->prev = block->prev; free( block ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -