/** * Deallocate space in memory * * A block of memory previously allocated using a call to malloc(), * calloc() or realloc() is deallocated, making it available again for * further allocations. * * Notice that this function leaves the value of ptr unchanged, hence * it still points to the same (now invalid) location, and not to the * null pointer. * * @param ptr * Pointer to a memory block previously allocated with malloc(), * calloc() or realloc() to be deallocated. If a null pointer is * passed as argument, no action occurs. */ void free(void *ptr) { // "If a null pointer is passed as argument, no action occurs." if (!ptr) return; void* block_ptr = ptr - sizeof(mem_dic); if ( MDIC(block_ptr)->occupy==false ) { D( printf("error in free(): the pos in %ld is not used\n",block_ptr - heap_ptr) ); } MDIC(block_ptr)->occupy = false; free_list_add(block_ptr, size2order( MDIC(block_ptr)->size )); void* merge_ptr = NULL; void* buddy_ptr = NULL; while( (merge_ptr = buddy_exist_not_occupied(block_ptr)) != NULL ) { // delete from free_list block_ptr and its buddy buddy_ptr = buddy_address(block_ptr); free_list_delete(block_ptr, size2order( MDIC(block_ptr)->size )); free_list_delete(buddy_ptr, size2order( MDIC(buddy_ptr)->size )); // merge buddy_ptr and block_ptr MDIC(merge_ptr)->size *= 2; MDIC(merge_ptr)->occupy = false; free_list_add(merge_ptr,size2order( MDIC(merge_ptr)->size )); block_ptr = merge_ptr; } return; }
void* split_block(void* block_ptr, size_t small_block_size) { /* error check */ if(MDIC(block_ptr) -> size < small_block_size) { D( printf("split_block: the oritinal size: %zu is smaller than the splitted size %zu\n", MDIC(block_ptr) -> size, small_block_size) ); return NULL; } else if (MDIC(block_ptr) -> size == small_block_size) return block_ptr; if (!divided2(small_block_size,MDIC(block_ptr)->size)) { D( printf("Error in split_block(): the original %zu can not be divided by %zu \n", MDIC(block_ptr)->size, small_block_size) ); return NULL; } /* end error check */ // if occupied, it is possbile that the block is being realloc. if(MDIC(block_ptr) -> occupy){ L(printf("split_block(): the block to be splitted is occupied, realloc is running\n")); } void* front_ptr = block_ptr; void* back_ptr = NULL; while(MDIC(front_ptr)->size > small_block_size) { if(!MDIC(front_ptr)->occupy) free_list_delete(front_ptr,size2order(MDIC(front_ptr)->size)); MDIC(front_ptr)->size /= 2; if(!MDIC(front_ptr)->occupy) free_list_add(front_ptr,size2order(MDIC(front_ptr)->size)); back_ptr = front_ptr + MDIC(front_ptr)->size; MDIC(back_ptr)->size = MDIC(front_ptr)->size; MDIC(back_ptr)->area_head = MDIC(front_ptr)->area_head; MDIC(back_ptr)->area_end = MDIC(front_ptr)->area_end; MDIC(back_ptr)->occupy = false; free_list_add(back_ptr,size2order(MDIC(back_ptr)->size)); } if (MDIC(front_ptr)->size != small_block_size) { D( printf("Fatal Error in split_block(): size is splited too small!\n") ); exit(0); } else return front_ptr; }
void* allocate_new_space(size_t size) { void* extend_heap_ptr = NULL; size_t one_time_alloc = find_one_time_sbrk_size(size); extend_heap_ptr = sbrk(one_time_alloc); MDIC(extend_heap_ptr) -> size = one_time_alloc; MDIC(extend_heap_ptr) -> occupy = false; free_list_add(extend_heap_ptr,size2order(MDIC(extend_heap_ptr)->size)); MDIC(extend_heap_ptr) -> area_head = extend_heap_ptr; MDIC(extend_heap_ptr) -> area_end = extend_heap_ptr + one_time_alloc; total_size += one_time_alloc; if(heap_ptr == NULL) heap_ptr = extend_heap_ptr; L(printf("allocate_new_space(): sbrked %zu bytes at loc %zu, total_size: %zu\n", MDIC(extend_heap_ptr) -> size, (size_t)(extend_heap_ptr - heap_ptr) ,total_size)); if (MDIC(extend_heap_ptr) -> size >= size) { /* Split if necessary, then return */ if(size > MDIC(extend_heap_ptr)->size / 2) return extend_heap_ptr; return split_block(extend_heap_ptr,size); } else { D( printf("new area %zu is smaller than the size %zu needed\n",one_time_alloc,size ) ); exit(0); } }
void fusb_ephandle::reap_complete_writes () { // take a look at the completed list and xfer to free list after // checking for errors. libusb_transfer *lut; while ((lut = completed_list_get ()) != 0) { // Check for any errors or short writes that were reporetd in the transfer. // libusb1 sets status, actual_length. if (lut->status != LIBUSB_TRANSFER_COMPLETED) { LOG(ERR) << "Invalid LUT status " << lut->status; check_health (false); } else if (lut->actual_length != lut->length){ LOG(ERR) << "Improper write of " << lut->actual_length; check_health (false); } else check_health (true); free_list_add (lut); } }
bool fusb_ephandle::submit_lut (libusb_transfer *lut) { if (!d_devhandle->_submit_lut (lut)) { LOG(ERR) << "USB submission failed"; free_list_add (lut); check_health (false); return false; } return true; }
static int sep_list_from_area(const uint32_t prio, uint32_t order) { struct page *page = NULL; free_area_t *queue = NULL; struct list_head *head, *item = NULL; queue = buddy_list.free_area + order; while(queue && order < NR_MEM_LISTS) { if(queue->nr_free_pages > 0) { head = &(queue->lists[prio]); if(list_empty_careful(head)) { ++order; ++queue; } else { /*DD("sep list order = %d. prio = %d", order, prio);*/ if(free_list_del(head, order, &item) != 0) { return -1; } page = list_entry(item, struct page, list); --order; --(page->order); free_list_add(page, prio, order); page += (uint32_t)pow(2,order); free_list_add(page, prio,order); return order; } } ++order; ++queue; }
bool fusb_ephandle::reload_read_buffer () { assert (d_read_buffer >= d_read_buffer_end); libusb_transfer *lut; if (d_read_work_in_progress) { lut = d_read_work_in_progress; d_read_work_in_progress = 0; d_read_buffer = 0; d_read_buffer_end = 0; lut->actual_length = 0; if (!submit_lut (lut)) { LOG(ERR) << "Improper LUT submission"; return false; } } while (1) { while ((lut = completed_list_get ()) == 0 ) if (!d_devhandle->_reap(true)) { LOG(ERR) << "No libusb events"; check_health (false); return false; } if (lut->status != LIBUSB_TRANSFER_COMPLETED) { LOG(ERR) << "Improper read status " << lut->status; lut->actual_length = 0; free_list_add (lut); check_health (false); return false; } d_read_work_in_progress = lut; d_read_buffer = (unsigned char *) lut->buffer; d_read_buffer_end = d_read_buffer + lut->actual_length; check_health (true); return true; } }
/* * delete_pool() - Delete a memory pool. Helper function common to all * memory pool types. * * Parameters: * mgr: INPUT The handle to the pools manager * pool: INPUT The handle of the pool to delete * * Returns: * BCME_OK Pool deleted ok. * other Pool not deleted due to indicated error. * */ static int BCMATTACHFN(delete_pool)(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp) { bcm_mp_pool_h pool; /* Check parameters */ if ((mgr == NULL) || (poolp == NULL) || (*poolp == NULL)) { return (BCME_BADARG); } /* Verify that all memory objects have been freed back to the pool. */ pool = *poolp; if (pool->num_alloc != 0) { MPOOL_ERROR(("ERROR: %s: memory leak - nobj(%d) num_alloc(%d)\n", __FUNCTION__, pool->u.p.nobj, pool->num_alloc)); return (BCME_BUSY); } /* For pool manager allocated memory, free the contiguous block of memory objects. */ if ((BCM_MP_GET_POOL_TYPE(pool) == BCM_MP_TYPE_PREALLOC) && (pool->u.p.malloc_memstart != NULL)) { MFREE(mgr->osh, pool->u.p.malloc_memstart, pool->u.p.nobj * pool->u.p.padded_objsz); } /* Mark the memory pool as unused. */ BCM_MP_CLEAR_IN_USE(pool); /* Add object memory back to pool. */ free_list_add(&mgr->free_pools, (bcm_mp_free_list_t *) pool); mgr->npools--; *poolp = NULL; return (BCME_OK); }
/* * bcm_mp_free() - Free a memory pool object. * * Parameters: * pool: INPUT The handle to the pool. * objp: INPUT A pointer to the object to free. * * Returns: * BCME_OK Ok * other Error during free. * */ int bcm_mp_free(bcm_mp_pool_h pool, void *objp) { /* Check parameters */ ASSERT(pool != NULL); if (objp == NULL) { return (BCME_BADARG); } if (BCM_MP_GET_POOL_TYPE(pool) == BCM_MP_TYPE_PREALLOC) { /* Add object memory back to pool. */ free_list_add(&pool->u.p.free_objp, (bcm_mp_free_list_t *) objp); } else { /* Heap allocation memory pool. */ MFREE(pool->u.h.osh, objp, pool->objsz); } /* Update pool state. */ pool->num_alloc--; return (BCME_OK); }
/* * create_pool() - Create a new pool for fixed size objects. Helper function * common to all memory pool types. * * Parameters: * mgr: INPUT The handle to the pool manager * obj_sz: INPUT Size of objects that will be allocated by the new pool. * This is the size requested by the user. The actual size * of the memory object may be padded. * Must be > 0 for heap pools. Must be >= sizeof(void *) for * Prealloc pools. * padded_obj_sz: INPUT Size of objects that will be allocated by the new pool. * This is the actual size of memory objects. It is 'obj_sz' * plus optional padding required for alignment. * Must be > 0 for heap pools. Must be >= sizeof(void *) for * Prealloc pools. * nobj: INPUT Maximum number of concurrently existing objects to support. * Must be specified for Prealloc pool. Ignored for heap pools. * memstart INPUT Pointer to the memory to use, or NULL to malloc(). * Ignored for heap pools. * memsize INPUT Number of bytes referenced from memstart (for error checking). * Must be 0 if 'memstart' is NULL. Ignored for heap pools. * poolname INPUT For instrumentation, the name of the pool * type INPUT Pool type - BCM_MP_TYPE_xxx. * newp: OUTPUT The handle for the new pool, if creation is successful * * Returns: * BCME_OK Pool created ok. * other Pool not created due to indicated error. newpoolp set to NULL. * * */ static int BCMATTACHFN(create_pool)(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int padded_obj_sz, int nobj, void *memstart, char poolname[BCM_MP_NAMELEN], uint16 type, bcm_mp_pool_h *newp) { bcm_mp_pool_t *mem_pool = NULL; void *malloc_memstart = NULL; /* Check parameters */ if ((mgr == NULL) || (newp == NULL) || (obj_sz == 0) || (padded_obj_sz == 0) || (poolname == NULL) || (poolname[0] == '\0')) { return (BCME_BADARG); } /* Allocate memory object from pool. */ mem_pool = (bcm_mp_pool_t *) free_list_remove(&mgr->free_pools); if (mem_pool == NULL) { return (BCME_NOMEM); } /* For pool manager allocated memory, malloc the contiguous memory * block of objects. */ if ((type == BCM_MP_TYPE_PREALLOC) && (memstart == NULL)) { memstart = MALLOC(mgr->osh, padded_obj_sz * nobj); if (memstart == NULL) { free_list_add(&mgr->free_pools, (bcm_mp_free_list_t *) mem_pool); return (BCME_NOMEM); } malloc_memstart = memstart; } /* Init memory pool object (common). */ memset(mem_pool, 0, sizeof(*mem_pool)); mem_pool->objsz = obj_sz; BCM_MP_SET_POOL_TYPE(mem_pool, type); BCM_MP_SET_IN_USE(mem_pool); strncpy(mem_pool->name, poolname, sizeof(mem_pool->name)); mem_pool->name[sizeof(mem_pool->name)-1] = '\0'; if (type == BCM_MP_TYPE_PREALLOC) { /* Init memory pool object (Prealloc specific). */ mem_pool->u.p.nobj = (uint16) nobj; mem_pool->u.p.malloc_memstart = malloc_memstart; mem_pool->u.p.padded_objsz = padded_obj_sz; /* Chain all the memory objects onto the pool's free list. */ free_list_init(&mem_pool->u.p.free_objp, memstart, padded_obj_sz, nobj); } else { /* Init memory pool object (Heap specific). */ mem_pool->u.h.osh = mgr->osh; } mgr->npools++; *newp = mem_pool; return (BCME_OK); }