/* * This is a helper method used to merge a block with it's buddy if both the blocks are * free to be merged into one */ void merge_memBlock(metadata_t* memBlock) { int freelist_index = log_Base_2(memBlock->size) - 4; //We are subtracting 4 because the smallest memory block size we have is 16 //which should correspond to index 0, so log 16 = 4 - 4 would give us 0 metadata_t* buddy = getBuddy(memBlock); //first defining the cases where we cannot merge if(memBlock->size >= SBRK_SIZE) { //if the block has a size more than or equal to 2048 //then we cannot merge it into anything bigger so we just place it along with //2048 blocks and do not merge anything add_freelist_top(memBlock, 7); return; } else if (buddy->in_use || (buddy->size != memBlock->size)) { //If the block's buddy is in use or if the block's size does not match with the buddy's size then //we do not merge them instead we just place the block at the correct index and return add_freelist_top(memBlock, freelist_index); return; } //Removing the ones we are merging from their original position in the free list while (buddy == freelist[freelist_index] || memBlock == freelist[freelist_index]) { if(buddy == freelist[freelist_index]) { remove_freelist_top(buddy, freelist_index); //buddy's next becomes NULL } if(memBlock == freelist[freelist_index]) { remove_freelist_top(memBlock, freelist_index); //block's next becomes NULL } } //removing the block and buddy from their position in the linked list remove_from_freelist(memBlock); remove_from_freelist(buddy); if(memBlock > buddy) { buddy->size = buddy->size*2; merge_memBlock(buddy); } else { memBlock->size = memBlock->size*2; merge_memBlock(memBlock); } }
int hassign(struct object *o, handle_t h) { int rc; if (h > HTABSIZE / sizeof(handle_t)) return -EBADF; while (htabsize <= h) { rc = expand_htab(); if (rc < 0) return rc; } if (!HUSED(htab[h])) { // Not allocated, remove from freelist rc = remove_from_freelist(h); if (rc < 0) return rc; } else { // Handle already allocated, free handle struct object *oo = HOBJ(htab[h]); if (HPROT(htab[h])) return -EACCES; if (--oo->handle_count == 0) { rc = close_object(oo); if (oo->lock_count == 0) destroy_object(oo); if (rc < 0) return rc; } } // Assign handle to object htab[h] = (handle_t) o; o->handle_count++; return 0; }
static void move_node(dary *da, int from, int to) { int i; /* FIXME: Simply da->base[from] is enough is implemented correctly. */ int search_start = MAX(da->base[from] , 1); int search_limit = MIN(da->base[from] + 256, da->length); dprint("move node from %d to %d", from, to); remove_from_freelist(da, to); if (da->base[from] == 0) { da->base[to] = 0; } else { da->base[to] = da->base[from]; dprint("da->base[%d] = %d\n", to, da->base[from]); } da->check[to] = da->check[from]; for (i = search_start; i < search_limit; i++) { if (da->check[i] == from) { da->check[i] = to; } } da->values[to] = da->values[from]; da->values[from] = 0; /* FIXME: This line should be removed */ return_to_freelist(da, from); }
static void insert_node_to(dary *da, int m, int n, int k) { dprint("insert_node_to %d k = %d, from %d (base %d, check %d)", m, k, n, da->base[n], da->check[n]); remove_from_freelist(da, m); da->check[m] = n; }
/* Add an element into the freelist. Merge adjacent records if necessary. */ int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec) { /* Allocation and tailer lock */ if (tdb_lock(tdb, -1, F_WRLCK) != 0) return -1; /* set an initial tailer, so if we fail we don't leave a bogus record */ if (update_tailer(tdb, offset, rec) != 0) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n")); goto fail; } #if USE_RIGHT_MERGES /* Look right first (I'm an Australian, dammit) */ if (offset + sizeof(*rec) + rec->rec_len + sizeof(*rec) <= tdb->map_size) { tdb_off_t right = offset + sizeof(*rec) + rec->rec_len; struct tdb_record r; if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right)); goto left; } /* If it's free, expand to include it. */ if (r.magic == TDB_FREE_MAGIC) { if (remove_from_freelist(tdb, right, r.next) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right)); goto left; } rec->rec_len += sizeof(r) + r.rec_len; if (update_tailer(tdb, offset, rec) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); goto fail; } } } left: #endif /* Look left */ if (offset - sizeof(tdb_off_t) > TDB_DATA_START(tdb->header.hash_size)) { tdb_off_t left = offset - sizeof(tdb_off_t); struct tdb_record l; tdb_off_t leftsize; /* Read in tailer and jump back to header */ if (tdb_ofs_read(tdb, left, &leftsize) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left)); goto update; } /* it could be uninitialised data */ if (leftsize == 0 || leftsize == TDB_PAD_U32) { goto update; } left = offset - leftsize; if (leftsize > offset || left < TDB_DATA_START(tdb->header.hash_size)) { goto update; } /* Now read in the left record */ if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); goto update; } /* If it's free, expand to include it. */ if (l.magic == TDB_FREE_MAGIC) { /* we now merge the new record into the left record, rather than the other way around. This makes the operation O(1) instead of O(n). This change prevents traverse from being O(n^2) after a lot of deletes */ l.rec_len += sizeof(*rec) + rec->rec_len; if (tdb_rec_write(tdb, left, &l) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_left failed at %u\n", left)); goto fail; } if (update_tailer(tdb, left, &l) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); goto fail; } tdb_unlock(tdb, -1, F_WRLCK); return 0; } } update: /* Now, prepend to free list */ rec->magic = TDB_FREE_MAGIC; if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || tdb_rec_write(tdb, offset, rec) == -1 || tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset)); goto fail; } /* And we're done. */ tdb_unlock(tdb, -1, F_WRLCK); return 0; fail: tdb_unlock(tdb, -1, F_WRLCK); return -1; }