/*! * Free memory chunk * \param mpool Memory pool to be used (if NULL default pool is used) * \param chunk Chunk location (starting address) * \return 0 if successful, -1 otherwise */ int ffs_free ( ffs_mpool_t *mpool, void *chunk_to_be_freed ) { ffs_hdr_t *chunk, *before, *after; ASSERT ( mpool && chunk_to_be_freed ); chunk = chunk_to_be_freed - sizeof (size_t); MARK_FREE ( chunk ); /* mark it as free */ /* join with left? */ before = ( (void *) chunk ) - sizeof(size_t); if ( CHECK_FREE ( before ) ) { before = GET_HDR ( before ); ffs_remove_chunk ( mpool, before ); before->size += chunk->size; /* join */ chunk = before; } /* join with right? */ after = GET_AFTER ( chunk ); if ( CHECK_FREE ( after ) ) { ffs_remove_chunk ( mpool, after ); chunk->size += after->size; /* join */ } /* insert chunk in free list */ ffs_insert_chunk ( mpool, chunk ); /* set chunk tail */ CLONE_SIZE_TO_TAIL ( chunk ); return 0; }
/*! * Get free chunk with required size (or slightly bigger) * \param mpool Memory pool to be used (if NULL default pool is used) * \param size Requested chunk size * \return Block address, NULL if can't find adequate free chunk */ void *ffs_alloc ( ffs_mpool_t *mpool, size_t size ) { ffs_hdr_t *iter, *chunk; ASSERT ( mpool ); size += sizeof (size_t) * 2; /* add header and tail size */ if ( size < HEADER_SIZE ) size = HEADER_SIZE; /* align request size to higher 'size_t' boundary */ ALIGN_FW ( size ); iter = mpool->first; while ( iter != NULL && iter->size < size ) iter = iter->next; if ( iter == NULL ) return NULL; /* no adequate free chunk found */ if ( iter->size >= size + HEADER_SIZE ) { /* split chunk */ /* first part remains in free list, just update size */ iter->size -= size; CLONE_SIZE_TO_TAIL ( iter ); chunk = GET_AFTER ( iter ); chunk->size = size; } else { /* give whole chunk */ chunk = iter; /* remove it from free list */ ffs_remove_chunk ( mpool, chunk ); } MARK_USED ( chunk ); CLONE_SIZE_TO_TAIL ( chunk ); return ( (void *) chunk ) + sizeof (size_t); }