Esempio n. 1
0
    void* HeapManager::allocBlock(unsigned char alloc_size, char type, bool protect) {
        assert(alloc_size <= 255);
        unsigned char block_size;
        char* ptr = getAddress(alloc_size, block_size);

        if (ptr == NULL) {
            printf("We ran out of memory\n");
            exit(1);
        }

#if DEBUG_HEAP_ALLOC
        printf("ALLOC %i %i\n", (int)(ptr - heap), type);
#endif

        int next_free_block_size = 0;

        // I'm not at the end of heap, there is block after me
        if (block_size != 0) {
            next_free_block_size = block_size - alloc_size - HEAP_HEAD_SIZE;

            // if new free block would be smaller than minimum,
            // use whole block as is and do nothing, since we
            // reached other set-up block
            if (next_free_block_size < HEAP_MIN_BLOCK_SIZE) {
                alloc_size = block_size;
            // else create new block with new size
            } else {
                write_block_size(ptr + FULL_BLOCK_SIZE(alloc_size), (unsigned char)next_free_block_size);
                write_block_flags(ptr + FULL_BLOCK_SIZE(alloc_size), 0, 0, 1);
            }
        } else {
            write_block_size(ptr + FULL_BLOCK_SIZE(alloc_size), 0);
            write_block_flags(ptr + FULL_BLOCK_SIZE(alloc_size), 0, 0, 1);
        }

        write_block_size(ptr, alloc_size);
        write_block_flags(ptr, type, (char)(protect ? GC_PROTECTED : GC_WHITE), false);

        if (next_free_block == ptr) {
            next_free_block += FULL_BLOCK_SIZE(alloc_size);
        }

        return ptr + HEAP_HEAD_SIZE;
    }
Esempio n. 2
0
    void HeapManager::purgeHeap(bool force) {

        unsigned char block_size;
        char type, color;
        bool free;

        next_free_block = NULL;
        char* prev_block = NULL;
        unsigned char prev_size = 0;

        int p = 0;
        while (p < HEAP_SIZE - HEAP_HEAD_SIZE - HEAP_MIN_BLOCK_SIZE) {
            char* block = heap+p;

            read_block_size(block, block_size);

            if (block_size == 0) { // reached the end of used space
                if (next_free_block == NULL) { next_free_block = block; }
                if (prev_block != NULL) { write_block_size(prev_block, 0); }
                break;
            }

            read_block_flags(block, type, color, free);

            // free white blocks
            if (!free && (color == GC_WHITE || force)) {

#if DEBUG_HEAP_ALLOC
                printf("DEALLOC %i\n", (int)(block - heap));
#endif

                switch(type) {
                    case GC_TABLE:   ((Table*)       (block + HEAP_HEAD_SIZE))->~Table();        break;
                    case GC_UPVAL:   ((UpvalueRef*)  (block + HEAP_HEAD_SIZE))->~UpvalueRef();   break;
                    case GC_CLOSURE: ((Closure*)     (block + HEAP_HEAD_SIZE))->~Closure();      break;
                    case GC_STRING:  ((StringObject*)(block + HEAP_HEAD_SIZE))->~StringObject(); break;
                    case GC_NATIVE:  ((Native*)      (block + HEAP_HEAD_SIZE))->~Native();       break;
                    case GC_FILE:    ((File*)        (block + HEAP_HEAD_SIZE))->~File();         break;
                    default: break;
                }
                free = true;
            }

            if (!free) {
                write_block_flags(block, type, (char)(color == GC_PROTECTED ? GC_PROTECTED : GC_WHITE), free);
                prev_block = NULL;
            } else {
                if (next_free_block == NULL) { next_free_block = block; }

                // if possible, merge with previous free block
                if (prev_block != NULL && prev_size + block_size + HEAP_HEAD_SIZE <= HEAP_MAX_BLOCK_SIZE) {
                    write_block_size(prev_block, (unsigned char)(prev_size + block_size + HEAP_HEAD_SIZE));
                    prev_size = (unsigned char)(prev_size + block_size + HEAP_HEAD_SIZE);
                // otherwise just mark block as free
                } else {
                    write_block_flags(block, type, GC_WHITE, free);
                    prev_block = block;
                    prev_size = block_size;
                }
            }

            p += FULL_BLOCK_SIZE(block_size);
        }
    }
Esempio n. 3
0
static errcode_t undo_write_tdb(io_channel channel,
				unsigned long long block, int count)

{
	int size, sz;
	unsigned long long block_num, backing_blk_num;
	errcode_t retval = 0;
	ext2_loff_t offset;
	struct undo_private_data *data;
	TDB_DATA tdb_key, tdb_data;
	unsigned char *read_ptr;
	unsigned long long end_block;

	data = (struct undo_private_data *) channel->private_data;

	if (data->tdb == NULL) {
		/*
		 * Transaction database not initialized
		 */
		return 0;
	}

	if (count == 1)
		size = channel->block_size;
	else {
		if (count < 0)
			size = -count;
		else
			size = count * channel->block_size;
	}
	/*
	 * Data is stored in tdb database as blocks of tdb_data_size size
	 * This helps in efficient lookup further.
	 *
	 * We divide the disk to blocks of tdb_data_size.
	 */
	offset = (block * channel->block_size) + data->offset ;
	block_num = offset / data->tdb_data_size;
	end_block = (offset + size) / data->tdb_data_size;

	tdb_transaction_start(data->tdb);
	while (block_num <= end_block ) {

		tdb_key.dptr = (unsigned char *)&block_num;
		tdb_key.dsize = sizeof(block_num);
		/*
		 * Check if we have the record already
		 */
		if (tdb_exists(data->tdb, tdb_key)) {
			/* Try the next block */
			block_num++;
			continue;
		}
		/*
		 * Read one block using the backing I/O manager
		 * The backing I/O manager block size may be
		 * different from the tdb_data_size.
		 * Also we need to recalcuate the block number with respect
		 * to the backing I/O manager.
		 */
		offset = block_num * data->tdb_data_size;
		backing_blk_num = (offset - data->offset) / channel->block_size;

		count = data->tdb_data_size +
				((offset - data->offset) % channel->block_size);
		retval = ext2fs_get_mem(count, &read_ptr);
		if (retval) {
			tdb_transaction_cancel(data->tdb);
			return retval;
		}

		memset(read_ptr, 0, count);
		actual_size = 0;
		if ((count % channel->block_size) == 0)
			sz = count / channel->block_size;
		else
			sz = -count;
		retval = io_channel_read_blk64(data->real, backing_blk_num,
					     sz, read_ptr);
		if (retval) {
			if (retval != EXT2_ET_SHORT_READ) {
				free(read_ptr);
				tdb_transaction_cancel(data->tdb);
				return retval;
			}
			/*
			 * short read so update the record size
			 * accordingly
			 */
			tdb_data.dsize = actual_size;
		} else {
			tdb_data.dsize = data->tdb_data_size;
		}
		tdb_data.dptr = read_ptr +
				((offset - data->offset) % channel->block_size);
#ifdef DEBUG
		printf("Printing with key %lld data %x and size %d\n",
		       block_num,
		       tdb_data.dptr,
		       tdb_data.dsize);
#endif
		if (!data->tdb_written) {
			data->tdb_written = 1;
			/* Write the blocksize to tdb file */
			retval = write_block_size(data->tdb,
						  data->tdb_data_size);
			if (retval) {
				tdb_transaction_cancel(data->tdb);
				retval = EXT2_ET_TDB_ERR_IO;
				free(read_ptr);
				return retval;
			}
		}
		retval = tdb_store(data->tdb, tdb_key, tdb_data, TDB_INSERT);
		if (retval == -1) {
			/*
			 * TDB_ERR_EXISTS cannot happen because we
			 * have already verified it doesn't exist
			 */
			tdb_transaction_cancel(data->tdb);
			retval = EXT2_ET_TDB_ERR_IO;
			free(read_ptr);
			return retval;
		}
		free(read_ptr);
		/* Next block */
		block_num++;
	}
	tdb_transaction_commit(data->tdb);

	return retval;
}