static void * alloc_do_malloc (struct Alloc *alloc, uint32_t size) { if (size < (alloc->default_mmap_size - chunk_overhead ())) { uint8_t bucket = size_to_bucket (size); if (alloc->buckets[bucket] != 0) { // fast path. struct AllocAvailable *avail = alloc->buckets[bucket]; MARK_DEFINED (avail, sizeof (void *)); struct AllocAvailable *next = avail->next; MARK_UNDEFINED (avail, sizeof (void *)); alloc->buckets[bucket] = next; REPORT_MALLOC (avail, size); return (uint8_t *) avail; } // slow path struct AllocAvailable *avail = (struct AllocAvailable *) alloc_brk (alloc, bucket_to_size (bucket)); REPORT_MALLOC (avail, size); avail->next = 0; return (uint8_t *) avail; } else { alloc_chunk (alloc, size + chunk_overhead ()); uint8_t *buffer = alloc_brk (alloc, size); REPORT_MALLOC (buffer, size); return buffer; } }
void* HeapImpl::AllocLocked(size_t size) { if (size > kMaxBucketAllocationSize) { return MapAlloc(size); } int bucket = size_to_bucket(size); if (free_chunks_[bucket].empty()) { Chunk *chunk = new Chunk(this, bucket); free_chunks_[bucket].insert(chunk->node_); } return free_chunks_[bucket].next()->data()->Alloc(); }
static void alloc_do_free (struct Alloc *alloc, uint8_t * buffer, uint32_t size) { if (size < (alloc->default_mmap_size - chunk_overhead ())) { // return to bucket list. uint8_t bucket = size_to_bucket (size); struct AllocAvailable *avail = (struct AllocAvailable *) buffer; avail->next = alloc->buckets[bucket]; alloc->buckets[bucket] = avail; REPORT_FREE (buffer); } else { struct AllocMmapChunk *tmp, *prev; for (tmp = alloc->chunks, prev = 0; tmp != 0; prev = tmp, tmp = tmp->next) { if (tmp->buffer == buffer && tmp->size == size) { if (prev == 0) { alloc->chunks = tmp->next; } else { prev->next = tmp->next; } REPORT_FREE (buffer); system_munmap (tmp->buffer, tmp->size); return; } } // this should never happen but it happens in case of a double-free REPORT_FREE (buffer); } }
int main(int argc, char *argv[]) { tdb_off_t b_off, test; struct tdb_context *tdb; struct tdb_layout *layout; struct tdb_data data, key; tdb_len_t len; /* FIXME: Test TDB_CONVERT */ /* FIXME: Test lock order fail. */ plan_tests(42); data = tdb_mkdata("world", 5); key = tdb_mkdata("hello", 5); /* No coalescing can be done due to EOF */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); len = 1024; tdb_layout_add_free(layout, len, 0); tdb = tdb_layout_get(layout); ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == len); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(len)); /* Lock and fail to coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[1].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, len, &test) == 0); tdb_unlock_free_bucket(tdb, b_off); ok1(free_record_length(tdb, layout->elem[1].base.off) == len); ok1(test == layout->elem[1].base.off); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* No coalescing can be done due to used record */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_used(layout, key, data, 6); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and fail to coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[1].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 0); tdb_unlock_free_bucket(tdb, b_off); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(test == layout->elem[1].base.off); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* Coalescing can be done due to two free records, then EOF */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_free(layout, 2048, 0); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(free_record_length(tdb, layout->elem[2].base.off) == 2048); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket (first) free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[2].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 1024 + sizeof(struct tdb_used_record) + 2048); /* Should tell us it's erased this one... */ ok1(test == TDB_ERR_NOEXIST); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024 + sizeof(struct tdb_used_record) + 2048); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* Coalescing can be done due to two free records, then data */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_free(layout, 512, 0); tdb_layout_add_used(layout, key, data, 6); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(free_record_length(tdb, layout->elem[2].base.off) == 512); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[2].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 1024 + sizeof(struct tdb_used_record) + 512); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024 + sizeof(struct tdb_used_record) + 512); ok1(test == TDB_ERR_NOEXIST); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); /* Coalescing can be done due to three free records, then EOF */ layout = new_tdb_layout("run-03-coalesce.tdb"); tdb_layout_add_freetable(layout); tdb_layout_add_free(layout, 1024, 0); tdb_layout_add_free(layout, 512, 0); tdb_layout_add_free(layout, 256, 0); tdb = tdb_layout_get(layout); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(free_record_length(tdb, layout->elem[2].base.off) == 512); ok1(free_record_length(tdb, layout->elem[3].base.off) == 256); ok1(tdb_check(tdb, NULL, NULL) == 0); /* Figure out which bucket free entry is. */ b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024)); /* Lock and coalesce. */ ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0); test = layout->elem[2].base.off; ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024, &test) == 1024 + sizeof(struct tdb_used_record) + 512 + sizeof(struct tdb_used_record) + 256); ok1(tdb->file->allrecord_lock.count == 0 && tdb->file->num_lockrecs == 0); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024 + sizeof(struct tdb_used_record) + 512 + sizeof(struct tdb_used_record) + 256); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); tdb_layout_free(layout); ok1(tap_log_messages == 0); return exit_status(); }