void mem_pool::pool_free( void* ptr, size_t bytes ) { if( ptr ) pool_dealloc( ptr, bytes ); if( bytes <= MEMORY_POOL_MAX ) { int i; size_t index = LIST_INDEX( bytes ); size_t blk_count = BLOCK_COUNT( index ); mempage_t *erase = NULL, *prev = NULL, *curr = pool[index].first; if( pool_lock ) pool_lock( index ); while( curr ) { if( curr->count != blk_count ) /* 判断是否是空闲页 */ { prev = curr; curr = curr->next; } else { /* 从页面缓存中退出 */ for( i = 0; i < MEMORY_POOL_BUFFER; ++i ) { if( pool[index].buffer[i] == curr ) { pool[index].buffer[i] = NULL; break; } } if( prev ) prev->next = curr->next; /* 空闲页不在链首 */ else pool[index].first = curr->next; /* 空闲页在链首 */ /* 将空闲页释放 */ erase = curr; curr = curr->next; MEMFREE( erase ); --( pool[index].useable ); } /* end if */ } /* end while */ if( pool_unlock ) pool_unlock( index ); } }
int _gnix_buddy_alloc(gnix_buddy_alloc_handle_t *alloc_handle, void **ptr, uint32_t len) { uint32_t block_size, i = 0; GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); if (unlikely(!alloc_handle || !ptr || !len || len > alloc_handle->max)) { GNIX_WARN(FI_LOG_EP_CTRL, "Invalid parameter to _gnix_buddy_alloc.\n"); return -FI_EINVAL; } block_size = BLOCK_SIZE(len, MIN_BLOCK_SIZE); i = (uint32_t) LIST_INDEX(block_size, MIN_BLOCK_SIZE); fastlock_acquire(&alloc_handle->lock); if (__gnix_buddy_find_block(alloc_handle, i, ptr)) { fastlock_release(&alloc_handle->lock); GNIX_WARN(FI_LOG_EP_CTRL, "Could not allocate buddy block.\n"); return -FI_ENOMEM; } fastlock_release(&alloc_handle->lock); _gnix_set_bit(&alloc_handle->bitmap, __gnix_buddy_bitmap_index(*ptr, block_size, alloc_handle->base, alloc_handle->len, MIN_BLOCK_SIZE)); return FI_SUCCESS; }
int _gnix_buddy_free(gnix_buddy_alloc_handle_t *alloc_handle, void *ptr, uint32_t len) { uint32_t block_size; GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); if (unlikely(!alloc_handle || !len || len > alloc_handle->max || ptr >= (void *) ((uint8_t *) alloc_handle->base + alloc_handle->len) || ptr < alloc_handle->base)) { GNIX_WARN(FI_LOG_EP_CTRL, "Invalid parameter to _gnix_buddy_free.\n"); return -FI_EINVAL; } block_size = BLOCK_SIZE(len, MIN_BLOCK_SIZE); _gnix_clear_bit(&alloc_handle->bitmap, __gnix_buddy_bitmap_index(ptr, block_size, alloc_handle->base, alloc_handle->len, MIN_BLOCK_SIZE)); fastlock_acquire(&alloc_handle->lock); block_size = __gnix_buddy_coalesce(alloc_handle, &ptr, block_size); dlist_insert_tail(ptr, alloc_handle->lists + LIST_INDEX(block_size, MIN_BLOCK_SIZE)); fastlock_release(&alloc_handle->lock); return FI_SUCCESS; }
void mem_pool::pool_dealloc( void* ptr, size_t bytes ) { if( !ptr ) return; if( bytes <= MEMORY_POOL_MAX ) { size_t index = LIST_INDEX( bytes ); mempage_t *curr, *prev = NULL; unsigned char *begin, *end, *blk = (unsigned char*)ptr; if( pool_lock ) pool_lock( index ); curr = pool[index].first; while( curr ) { begin = (unsigned char*)curr + sizeof(mempage_t); end = begin + pool[index].page_size; if( blk < begin || blk >= end ) /* 判断ptr是否在当前页内 */ { prev = curr; curr = curr->next; } else { size_t blk_size = BLOCK_SIZE( index ); /* 检查ptr是否正确 */ if( (blk - begin) % blk_size == 0 ) { /* 将内存块回收至链表首部 */ memblk_t* pblk = (memblk_t*)ptr; pblk->next = curr->free; curr->free = pblk; /* 如果回收前内存页已满,则将可用页数加一 */ if( curr->count == 0 ) ++( pool[index].useable ); ++( curr->count ); /* 如果当前页不在链首,则将之移至链首 */ if( pool[index].first != curr ) { prev->next = curr->next; curr->next = pool[index].first; pool[index].first = curr; } ++pool_dealloc_count; } break; } /* end else */ } /* end while */ if( pool_unlock ) pool_unlock( index ); return; } /* end if */ /* ptr不是由内存池分配 */ MEMFREE( ptr ); ++pool_dealloc_count; }
void* mem_pool::pool_alloc( size_t bytes ) { void* ptr = NULL; if( bytes > MEMORY_POOL_MAX ) { ptr = MEMALLOC( bytes ); } else { size_t index = LIST_INDEX( bytes ); if( pool_lock ) pool_lock( index ); if( pool[index].first && pool[index].useable > 0 ) { int i; mempage_t *prev = NULL, *curr = NULL; /* 先查找页面缓存 */ for( i = 0; i < MEMORY_POOL_BUFFER; ++i ) { if( pool[index].buffer[i] ) { ptr = pool[index].buffer[i]->free; pool[index].buffer[i]->free = pool[index].buffer[i]->free->next; --( pool[index].buffer[i]->count ); /* 如果该页已无空闲块,则将该页自页面缓存中退出 */ if( pool[index].buffer[i]->count == 0 ) { --( pool[index].useable ); pool[index].buffer[i] = NULL; } else { if( i > 0 ) { /* 如果该页不在缓存首,则将该页调整至缓存首 */ pool[index].buffer[0] = pool[index].buffer[i]; pool[index].buffer[i] = NULL; } } goto EXIT_POOL_ALLOC; } } /* end for */ /* 页面缓存为空,则遍历链中的所有内存页寻找空闲的内存块 */ curr = pool[index].first; while( curr ) { if( curr->count == 0 ) /* 该页中没有空闲块 */ { /* 进入下一页 */ prev = curr; curr = curr->next; } else /* 该页中有空闲块 */ { size_t page_count = 0; /* 统计遍历过的可用内存页 */ ptr = curr->free; curr->free = curr->free->next; --( curr->count ); if( curr->count == 0 ) --( pool[index].useable ); /* 继续遍历链表,寻找其他还有空闲块的页面,将之放入页面缓存 */ while( curr && page_count < pool[index].useable ) { if( curr->count != 0 ) { /* 页面缓存还有位置则放入页面缓存 */ if( page_count < MEMORY_POOL_BUFFER ) pool[index].buffer[page_count] = curr; ++page_count; /* 如果当前页未满并且不在链首,则将之移至链首 */ if( pool[index].first != curr ) { prev->next = curr->next; /* 保存下一页 */ curr->next = pool[index].first; pool[index].first = curr; curr = prev->next; /* 进入下一页 */ continue; } } /* 进入下一页 */ prev = curr; curr = curr->next; } goto EXIT_POOL_ALLOC; } /* end else */ } /* end while */ } /* end if pool[index].useable > 0 */ else { /* 该链下未分配内存页或无空闲块,此时需增加新的内存页 */ mempage_t* pg = NULL; size_t blk_size = BLOCK_SIZE( index ); /* 如果 page_size = 0,则计算该内存链下每个内存页需占用的字节数 */ if( 0 == pool[index].page_size ) { if( DEFAULT_PAGE_SIZE % blk_size == 0 ) pool[index].page_size = DEFAULT_PAGE_SIZE; else pool[index].page_size = (DEFAULT_PAGE_SIZE / blk_size) * blk_size; } pg = (mempage_t*)MEMALLOC( sizeof(mempage_t) + pool[index].page_size ); if( pg ) { memblk_t* curr = NULL; size_t i, blk_count = BLOCK_COUNT( index ); pg->next = pool[index].first; pool[index].first = pg; /* 将内存页中的所有内存块串联成一个链表 */ curr = (memblk_t*)((unsigned char*)pg + sizeof(mempage_t)); pg->free = curr; for( i = 1; i < blk_count; ++i ) { curr->next = (memblk_t*)((unsigned char*)curr + blk_size); curr = curr->next; } curr->next = NULL; ptr = pg->free; pg->free = pg->free->next; pg->count = blk_count - 1; ++( pool[index].useable ); pool[index].buffer[0] = pg; } } EXIT_POOL_ALLOC: if( pool_unlock ) pool_unlock( index ); } /* end else */ if( ptr ) ++pool_alloc_count; return ptr; }