alloc_status mem_del_alloc(pool_pt pool, alloc_pt alloc) { // get mgr from pool by casting the pointer to (pool_mgr_pt) pool_mgr_pt poolMgr = (pool_mgr_pt) pool; // temporary node pt to check if the node if found node_pt node = (node_pt) alloc; // node that will hold the next node from the node that will be deleted node_pt next = NULL; // prev node from deleteNode node_pt prev = NULL; // this node will be used as a temporary storage node_pt deleteNode = NULL; // find the node in the node heap for(int i = 0; i< poolMgr->total_nodes; ++i){ if(node == &poolMgr->node_heap[i]){ deleteNode = &poolMgr->node_heap[i]; break; } } // make sure it's found if (deleteNode != NULL); else{ return ALLOC_FAIL; } next = deleteNode->next; prev = deleteNode->prev; deleteNode->allocated = 0; // update metadata (num_allocs, alloc_size) poolMgr->pool.num_allocs--; poolMgr->pool.alloc_size -= deleteNode->alloc_record.size; // if the next node in the list is a gap, merge deleteNode to it if(deleteNode->next != NULL && deleteNode->next->allocated == 0) { if(_mem_remove_from_gap_ix(poolMgr, 0, next) == ALLOC_FAIL) { return ALLOC_FAIL; } deleteNode->alloc_record.size += next->alloc_record.size; // update node as unused next->used = 0; // update metadata (used nodes) --(poolMgr->used_nodes); // update linked list: if (next->next) { next->next->prev = deleteNode; deleteNode->next = next->next; } else { deleteNode->next = NULL; } next->next = NULL; next->prev = NULL; } // check if the prev node in the list a gap and merges it if it is if(deleteNode->prev!= NULL && deleteNode->prev->allocated == 0) { if(_mem_remove_from_gap_ix(poolMgr, 0, prev) == ALLOC_FAIL) { return ALLOC_FAIL; } prev->alloc_record.size += deleteNode->alloc_record.size; // update metadata (used_nodes) --(poolMgr->used_nodes); deleteNode->used = 0; // update linked list if (deleteNode->next) { prev->next = deleteNode->next; deleteNode->next->prev = prev; } else { prev->next = NULL; } deleteNode = prev; } // check success if (_mem_add_to_gap_ix(poolMgr, deleteNode->alloc_record.size, deleteNode) == ALLOC_OK) { return ALLOC_OK; } else { return ALLOC_FAIL; } }
alloc_status mem_del_alloc(pool_pt pool, alloc_pt alloc) { // get mgr from pool by casting the pointer to (pool_mgr_pt) pool_mgr_pt pool_mgr = (pool_mgr_pt) pool; // get node from alloc by casting the pointer to (node_pt) node_pt node = (node_pt) alloc; node_pt node_delete; // locate the node in the node heap for(int i=0;i < pool_mgr->total_nodes; i++){ if(pool_mgr->node_heap[i].alloc_record.mem == node->alloc_record.mem){ node_delete = &pool_mgr->node_heap[i]; break; }; }; // verify that node is not null if(node_delete == NULL){ return ALLOC_NOT_FREED; }; // set node to gap node_delete->allocated = 0; // update pool manager variables pool_mgr->pool.num_allocs--; pool_mgr->pool.alloc_size = pool_mgr->pool.alloc_size - node_delete->alloc_record.size; //if the next node is also a gap, merge to one gap node_pt merge_node; if(node_delete->next != NULL && node_delete->next->allocated == 0 && node_delete->next->used == 1){ merge_node = node_delete->next; // remove the next node from the gap index _mem_remove_from_gap_ix(pool_mgr,merge_node->alloc_record.size,merge_node); // add size to the gap node node_delete->alloc_record.size = node_delete->alloc_record.size + node_delete->next->alloc_record.size; // set merged node used variable to zero merge_node->used = 0; // deincriment used nodes pool_mgr->used_nodes--; // set the merge node next prev pointer to //node delete and node delete next to the merge node next // or set it to null if the merged next is null if (merge_node->next) { merge_node->next->prev = node_delete; node_delete->next = merge_node->next; } else { node_delete->next = NULL; } merge_node->next = NULL; merge_node->prev = NULL; merge_node->alloc_record.size = 0; merge_node->alloc_record.mem = NULL; }; // add the node delete to the gap index _mem_add_to_gap_ix(pool_mgr,node_delete->alloc_record.size,node_delete); //if the node previous to the node to delete is a gap, merge the node node_pt prev_node; if (node_delete->prev != NULL && node_delete->prev->used == 1 && node_delete->prev->allocated == 0) { prev_node = node_delete->prev; // remove the previous node and node to delete from the gap index _mem_remove_from_gap_ix(pool_mgr, prev_node->alloc_record.size, prev_node); _mem_remove_from_gap_ix(pool_mgr, node_delete->alloc_record.size,node_delete); // add the node to delete to the previous node prev_node->alloc_record.size = node_delete->alloc_record.size + node_delete->prev->alloc_record.size; // clear the metadata from the node to delete node_delete->alloc_record.size = 0; node_delete->alloc_record.mem = NULL; node_delete->used = 0; node_delete->allocated = 0; // deincrement used nodes pool_mgr->used_nodes--; // set the prev node next pointer to node delete next // and the prev pointer from the node delete next to prev node if (node_delete->next) { prev_node->next = node_delete->next; node_delete->next->prev = prev_node; } else { prev_node->next = NULL; } node_delete->next = NULL; node_delete->prev = NULL; // add the previous node to the gap index _mem_add_to_gap_ix(pool_mgr,prev_node->alloc_record.size,prev_node); }; return ALLOC_OK; }
alloc_pt mem_new_alloc(pool_pt pool, size_t size) { // get mgr from pool by casting the pointer to (pool_mgr_pt) // variables that will be used: pool_mgr_pt poolMgr = (pool_mgr_pt) pool; node_pt newNode = NULL; node_pt newGap = NULL; int i = 0; int j = 0; int remainGap = 0; // check if any gaps, return null if none if(poolMgr->gap_ix[0].node == NULL){ return NULL; } // expand heap node, if necessary, quit on error if ((poolMgr->used_nodes / poolMgr->total_nodes) > MEM_NODE_HEAP_FILL_FACTOR && _mem_resize_node_heap(poolMgr) != ALLOC_OK) { _mem_resize_node_heap(poolMgr); } if (poolMgr->used_nodes > poolMgr->total_nodes) { return NULL; } // if policy == FIRST_FIT, (node heap) if(poolMgr->pool.policy == FIRST_FIT){ while((i < poolMgr->total_nodes) && (poolMgr->node_heap[i].allocated != 0 || poolMgr->node_heap[i].alloc_record.size < size)){ ++i; } // check if node found if(i == poolMgr->total_nodes){ return NULL; } newNode = &poolMgr->node_heap[i]; } // if policy == BEST_FIT, (gap ix) else if(poolMgr->pool.policy == BEST_FIT){ if(poolMgr->pool.num_gaps > 0) { while (i < poolMgr->pool.num_gaps && poolMgr->gap_ix[i + 1].size >= size) { if(poolMgr->gap_ix[i].size == size){ break; } ++i; } } else { return NULL; } newNode = poolMgr->gap_ix[i].node; } // check if node found if(newNode == NULL){ return NULL; } // update metadata (num_allocs, alloc_size) ++(poolMgr->pool.num_allocs); poolMgr->pool.alloc_size += size; // calculate the size of the remaining gap, if any if(newNode->alloc_record.size - size > 0){ remainGap = newNode->alloc_record.size - size; } _mem_remove_from_gap_ix(poolMgr, size, newNode); // convert gap_node to an allocation node of given size newNode->alloc_record.size = size; newNode->allocated = 1; newNode->used = 1; // adjust node heap: // if remaining gap, need a new node if(remainGap != 0) { // find an unused one in the node heap while (poolMgr->node_heap[j].used != 0) { ++j; } newGap = &poolMgr->node_heap[j]; // make sure one was found if(newGap == NULL){ return NULL; } else { newGap->alloc_record.size = remainGap; newGap->used = 1; newGap->allocated = 0; } newGap->next = newNode->next; // update linked list (new node right after the node for allocation) if(newNode->next != NULL){ newNode->next->prev = newGap; } ++(poolMgr->used_nodes); newNode->next = newGap; newGap->prev = newNode; // add to gap index _mem_add_to_gap_ix(poolMgr, remainGap, newGap); } // return allocation record by casting the node to (alloc_pt) return (alloc_pt) newNode; }
alloc_pt mem_new_alloc(pool_pt pool, size_t size) { // get mgr from pool by casting the pointer to (pool_mgr_pt) pool_mgr_pt pool_mgr = (pool_mgr_pt) pool; // verify if there are any gaps in the pool if (pool_mgr->pool.num_gaps == 0) { return NULL; }; // resize node heap if nessisary _mem_resize_node_heap(pool_mgr); // check if used nodes are greater than total nodes if (pool_mgr->used_nodes >= pool_mgr->total_nodes) { return NULL; }; // if FIRST_FIT, then find the first unallocated node with appropriate size in the node heap node_pt alloc_node; if (pool_mgr->pool.policy == FIRST_FIT) { for (int i = 0; i < pool_mgr->total_nodes; i++) { if (pool_mgr->node_heap[i].alloc_record.size >= size && pool_mgr->node_heap[i].allocated == 0) { alloc_node = &pool_mgr->node_heap[i]; break; }else{ alloc_node = NULL; }; } }; // if BEST_FIT, then find the first gap node with appropriate size in the gap index if(pool_mgr->pool.policy == BEST_FIT){ for (int i = 0; i < pool_mgr->pool.num_gaps; i++) { if (pool_mgr->gap_ix[i].node->alloc_record.size >= size && pool_mgr->gap_ix[i].node->allocated == 0) { alloc_node = pool_mgr->gap_ix[i].node; break; }else{ alloc_node = NULL; }; } }; // check if node found if (alloc_node == NULL) { return NULL; }; // incriment num_allocs and add the size of the new allocation to alloc_size pool->num_allocs++; pool->alloc_size += size; // calculate the size of the remaining gap size_t gap_remain; gap_remain = alloc_node->alloc_record.size - size; // remove node from gap index _mem_remove_from_gap_ix(pool_mgr, size, alloc_node); // update the variables of the new allocated node alloc_node->allocated = 1; alloc_node->alloc_record.size = size; //use new node to handle remaining gap node_pt gap_node; // locate an unused node in the node heap if(gap_remain != 0) { for (int i = 0; i < pool_mgr->total_nodes; i++) { if (pool_mgr->node_heap[i].used == 0) { gap_node = &pool_mgr->node_heap[i]; break; } } // verify that the node we found exists if (gap_node == NULL) { //gap not found! } // initialize the gap node by adding the appropriate values gap_node->alloc_record.size = gap_remain; gap_node->alloc_record.mem = alloc_node->alloc_record.mem + size; gap_node->used = 1; gap_node->allocated = 0; // incriment the used nodes of the pool manager pool_mgr->used_nodes++; // set new allocated node to point next to the remaining gap node if (alloc_node->next == NULL) { alloc_node->next = gap_node; gap_node->next = NULL; gap_node->prev = alloc_node; } else { gap_node->next = alloc_node->next; alloc_node->next->prev = gap_node; alloc_node->next = gap_node; gap_node->prev = alloc_node; }; // add to gap index _mem_add_to_gap_ix(pool_mgr, gap_remain, gap_node); } // verify that the new allocated node was created succesfully if(alloc_node == NULL){ return NULL; }; // return allocation record by casting the node to (alloc_pt) return (alloc_pt) alloc_node; }
alloc_status mem_del_alloc(pool_pt pool, alloc_pt alloc) { // get mgr from pool by casting the pointer to (pool_mgr_pt) pool_mgr_pt pool_mgr = (pool_mgr_pt) pool; // get node from alloc by casting the pointer to (node_pt) node_pt node = (node_pt) alloc; // find the node in the node heap int found = 0; for (int i = 0; i < pool_mgr->total_nodes; i++) { if (&pool_mgr->node_heap[i] == node) { found = 1; break; } } // this is node-to-delete // make sure it's found if (!found) return ALLOC_FAIL; // convert to gap node node->allocated = 0; // update metadata (num_allocs, alloc_size) pool_mgr->pool.num_allocs--; pool_mgr->pool.alloc_size -= alloc->size; // if the next node in the list is also a gap, merge into node-to-delete if (node->next != NULL && node->next->allocated == 0) { // remove the next node from gap index // check success if (_mem_remove_from_gap_ix(pool_mgr, node->next->alloc_record.size, node->next) != ALLOC_OK) return ALLOC_FAIL; // add the size to the node-to-delete node->alloc_record.size += node->next->alloc_record.size; // update node as unused node->next->used = 0; // update metadata (used nodes) pool_mgr->used_nodes--; // update linked list: /* if (next->next) { next->next->prev = node_to_del; node_to_del->next = next->next; } else { node_to_del->next = NULL; } next->next = NULL; next->prev = NULL; */ node_pt node_to_del = node->next; if (node->next->next) { node->next->next->prev = node; node->next = node->next->next; } else { node->next = NULL; } node_to_del->next = NULL; node_to_del->prev = NULL; } // this merged node-to-delete might need to be added to the gap index // but one more thing to check... // if the previous node in the list is also a gap, merge into previous! if (node->prev != NULL && node->prev->allocated == 0) { // remove the previous node from gap index // check success if (_mem_remove_from_gap_ix(pool_mgr, node->prev->alloc_record.size, node->prev) != ALLOC_OK) return ALLOC_FAIL; // add the size of node-to-delete to the previous node->prev->alloc_record.size += node->alloc_record.size; // update node-to-delete as unused node->used = 0; // update metadata (used_nodes) pool_mgr->used_nodes--; // update linked list /* if (node_to_del->next) { prev->next = node_to_del->next; node_to_del->next->prev = prev; } else { prev->next = NULL; } node_to_del->next = NULL; node_to_del->prev = NULL; */ node_pt prev_node = node->prev; if (node->next) { node->prev->next = node->next; node->next->prev = node->prev; } else { node->prev->next = NULL; } node->next = NULL; node->prev = NULL; // change the node to add to the previous node! node = prev_node; } // add the resulting node to the gap index // check success if (_mem_add_to_gap_ix(pool_mgr, node->alloc_record.size, node) != ALLOC_OK) return ALLOC_FAIL; return ALLOC_OK; }
alloc_pt mem_new_alloc(pool_pt pool, size_t size) { // get mgr from pool by casting the pointer to (pool_mgr_pt) pool_mgr_pt pool_mgr = (pool_mgr_pt) pool; // check if any gaps, return null if none if (pool_mgr->pool.num_gaps == 0) return NULL; // expand heap node, if necessary, quit on error if (_mem_resize_node_heap(pool_mgr) != ALLOC_OK) return NULL; // check used nodes fewer than total nodes, quit on error if (pool_mgr->used_nodes > pool_mgr->total_nodes) return NULL; // get a node for allocation: node_pt node = NULL; // if FIRST_FIT, then find the first sufficient node in the node heap if (pool->policy == FIRST_FIT) { for (int i = 0; i < pool_mgr->total_nodes; i ++) { if (pool_mgr->node_heap[i].used == 1 && pool_mgr->node_heap[i].allocated == 0 && pool_mgr->node_heap[i].alloc_record.size >= size) { node = &pool_mgr->node_heap[i]; break; } } // if BEST_FIT, then find the first sufficient node in the gap index } else if (pool->policy == BEST_FIT) { for (int i = 0; i < pool_mgr->gap_ix_capacity && node == NULL; i++) { if (pool_mgr->gap_ix[i].size >= size) node = pool_mgr->gap_ix[i].node; } } else { return NULL; } // check if node found if (node == NULL) { return NULL; } // update metadata (num_allocs, alloc_size) pool->num_allocs++; pool->alloc_size += size; // calculate the size of the remaining gap, if any size_t remaining_gap_size = node->alloc_record.size - size; // remove node from gap index if (_mem_remove_from_gap_ix(pool_mgr, size, node) != ALLOC_OK) return NULL; // convert gap_node to an allocation node of given size node->allocated = 1; node->alloc_record.size = size; // adjust node heap: // if remaining gap, need a new node if (remaining_gap_size != 0) { // find an unused one in the node heap /* node_pt unused_node = pool_mgr->node_heap; while (unused_node != NULL && unused_node->used != 0) { unused_node = unused_node->next; }*/ node_pt unused_node = NULL; for (int i = 0; i < pool_mgr->total_nodes; i ++) { if (pool_mgr->node_heap[i].used == 0) { unused_node = &pool_mgr->node_heap[i]; break; } } // make sure one was found if (unused_node == NULL) return NULL; // initialize it to a gap node unused_node->allocated = 0; unused_node->used = 1; unused_node->alloc_record.size = remaining_gap_size; unused_node->alloc_record.mem = node->alloc_record.mem + size; // update metadata (used_nodes) pool_mgr->used_nodes++; // update linked list (new node right after the node for allocation) unused_node->next = node->next; if (node->next != NULL) { node->next->prev = unused_node; } else { unused_node->next = NULL; } node->next = unused_node; unused_node->prev = node; // add to gap index // check if successful if (_mem_add_to_gap_ix(pool_mgr, remaining_gap_size, unused_node) != ALLOC_OK) return NULL; } // return allocation record by casting the node to (alloc_pt) return (alloc_pt) node; }
pool_pt mem_pool_open(size_t size, alloc_policy policy) { // make sure there the pool store is allocated if (pool_store == NULL) return NULL; // expand the pool store, if necessary _mem_resize_pool_store(); // allocate a new mem pool mgr pool_mgr_pt pool_mgr = malloc(sizeof(pool_mgr_t)); // check success, on error return null if (pool_mgr == NULL) return NULL; // allocate a new memory pool pool_mgr->pool.mem = malloc(size); pool_mgr->pool.policy = policy; pool_mgr->pool.total_size = size; // check success, on error deallocate mgr and return null if (pool_mgr->pool.mem == NULL) { free(pool_mgr->pool.mem); free(pool_mgr); return NULL; } // allocate a new node heap pool_mgr->node_heap = calloc(MEM_NODE_HEAP_INIT_CAPACITY, sizeof(node_t)); pool_mgr->total_nodes = MEM_NODE_HEAP_INIT_CAPACITY; // check success, on error deallocate mgr/pool and return null if (pool_mgr->node_heap == NULL) { free(pool_mgr->pool.mem); free(pool_mgr->node_heap); free(pool_mgr); return NULL; } // allocate a new gap index pool_mgr->gap_ix = calloc(MEM_GAP_IX_INIT_CAPACITY, sizeof(gap_t)); pool_mgr->gap_ix_capacity = MEM_GAP_IX_INIT_CAPACITY; // check success, on error deallocate mgr/pool/heap and return null if (pool_mgr->gap_ix == NULL) { free(pool_mgr->pool.mem); free(pool_mgr->node_heap); free(pool_mgr->gap_ix); free(pool_mgr); return NULL; } // assign all the pointers and update meta data: // initialize top node of node heap pool_mgr->node_heap[0].alloc_record.mem = pool_mgr->pool.mem; pool_mgr->node_heap[0].alloc_record.size = size; pool_mgr->node_heap[0].used = 1; pool_mgr->used_nodes = 1; pool_mgr->pool.num_gaps = 0; // initialize top node of gap index _mem_add_to_gap_ix(pool_mgr, size, &pool_mgr->node_heap[0]); //pool_mgr->gap_ix[0].node = &pool_mgr->node_heap[0]; //pool_mgr->gap_ix[0].node->alloc_record.size = size; // link pool mgr to pool store pool_store[pool_store_size] = pool_mgr; pool_store_size++; // return the address of the mgr, cast to (pool_pt) return (pool_pt) pool_mgr; }
alloc_pt mem_new_alloc(pool_pt pool, size_t size) { // get mgr from pool by casting the pointer to (pool_mgr_pt) pool_mgr_pt mem_pool_mgr = (pool_mgr_pt) pool; // check if any gaps, return null if none if(pool->num_gaps == 0) { return NULL; } // expand heap node, if necessary, quit on error if(mem_pool_mgr->total_nodes < mem_pool_mgr->used_nodes) { mem_pool_mgr->total_nodes += MEM_NODE_HEAP_EXPAND_FACTOR; } // check used nodes fewer than total nodes, quit on error if(mem_pool_mgr->total_nodes < mem_pool_mgr->used_nodes) { return NULL; } // get a node for allocation: node_pt nodeA = NULL; node_pt gapA = NULL; int i = 0; // if FIRST_FIT, then find the first sufficient node in the node heap if(mem_pool_mgr->pool.policy == FIRST_FIT) { while(i < mem_pool_mgr->total_nodes) if((mem_pool_mgr->node_heap[i].allocated != 0 || mem_pool_mgr->node_heap[i].alloc_record.size < size)) ++i; nodeA = &mem_pool_mgr->node_heap[i]; } // if BEST_FIT, then find the first sufficient node in the gap index if(mem_pool_mgr->pool.policy == BEST_FIT) { while(i < mem_pool_mgr->gap_ix->size) if(i < mem_pool_mgr->pool.num_gaps && mem_pool_mgr->gap_ix[i + 1].size >= size) ++i; nodeA = mem_pool_mgr->gap_ix[i].node; } // check if node found if (nodeA = NULL) { return NULL; } // update metadata (num_allocs, alloc_size) (mem_pool_mgr->pool.num_allocs)++; mem_pool_mgr->pool.alloc_size += size; // calculate the size of the remaining gap, if any int remainGap = 0; if(nodeA->alloc_record.size - size > 0) { remainGap = nodeA->alloc_record.size - size; } // remove node from gap index _mem_remove_from_gap_ix(mem_pool_mgr, size, nodeA); // convert gap_node to an allocation node of given size nodeA->alloc_record.size = size; nodeA->allocated = 1; nodeA->used = 1; // adjust node heap: // if remaining gap, need a new node // find an unused one in the node heap // make sure one was found // initialize it to a gap node int j = 0; if(remainGap > 0) { while(mem_pool_mgr->node_heap[j].used > 0) { gapA = &mem_pool_mgr->node_heap[j]; ++j; } } // update metadata (used_nodes) (mem_pool_mgr->used_nodes)++; // update linked list (new node right after the node for allocation) if(nodeA->next != NULL) { nodeA->next->prev = gapA; gapA->prev = nodeA; } // add to gap index _mem_add_to_gap_ix(mem_pool_mgr, remainGap, gapA); // check if successful // return allocation record by casting the node to (alloc_pt) return (alloc_pt) nodeA; }