Пример #1
0
uintptr_t* kalloc(uint32_t asize)
{
	uint32_t size;
	if(!kernel_heap)
		return 0;
	
	// Align allocation size on uint32_t
	uint8_t mod = asize % 4;
	if(mod > 0)
		size = asize + 4 - (uint32_t)mod;
	else
		size = asize;
	
	uint32_t required_size = size + 2*(sizeof(block_footer_t) + sizeof(block_header_t));
	
	block_header_t* blk = kernel_heap->heap_begin;
	
	// Iterate in our heap, and stops when we found a block, or there is no remaining blocks
	while((blk->size < required_size ||blk->flags == 1) && next_block(blk))
		blk = next_block(blk);

	// We found a block !
	if(blk->size >= required_size && blk->flags == 0 && blk->magic == HEAP_HEADER_MAGIC)
	{
		if(blk->size == required_size) {
			blk->flags = 1;
			return block_data_space(blk);
		} else {
			// Update block data
			block_footer_t* footer = get_footer(blk);
			uint32_t old_size = blk->size;
			blk->size = size + sizeof(block_header_t) + sizeof(block_footer_t);
			blk->flags = 1;
			
			// Create footer for block
			block_footer_t* new_footer = (block_footer_t*)((uintptr_t)blk + blk->size - sizeof(block_footer_t));
			new_footer->header = blk;
			new_footer->magic = HEAP_FOOTER_MAGIC;

			// Create new block next to it
			block_header_t* new_block = (block_header_t*)((uintptr_t)new_footer + sizeof(block_footer_t));
			new_block->magic = HEAP_HEADER_MAGIC;
			new_block->flags = 0;
			new_block->size = old_size - blk->size;
			
			// Update footer data to link to the newly created block
			footer->header = new_block;
			
			block_footer_t* check = get_footer(new_block);
			block_footer_t* check2 = get_footer(blk);
			return block_data_space(blk);
		}
	} else {
		panic("Kernel heap out of memory\n", 0);
		return 0;
	}
}
Пример #2
0
 /**
  * Free memory
  */
 void free(void* pos) {
     uint32_t* block = reinterpret_cast<uint32_t*>(pos);
     block--;
     if (!is_allocated(next_block(block))) {
         uint32_t new_size = size_of_block(block) + 4 + size_of_block(next_block(block));
         record(block, new_size, kFree);
     } else {
         record(block, size_of_block(block), kFree);
     }
 }
Пример #3
0
// DM_write: 70734 events, 0 overruns, 167806us elapsed, 2us avg, min 1us max 34us 0.620us rms
bool DataFlash_MAVLink::WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical)
{
    if (!WritesOK()) {
        return false;
    }

    if (!semaphore->take_nonblocking()) {
        dropped++;
        return false;
    }

    if (! WriteBlockCheckStartupMessages()) {
        semaphore->give();
        return false;
    }

    if (bufferspace_available() < size) {
        if (_startup_messagewriter->finished()) {
            // do not count the startup packets as being dropped...
            dropped++;
        }
        semaphore->give();
        return false;
    }

    uint16_t copied = 0;

    while (copied < size) {
        if (_current_block == nullptr) {
            _current_block = next_block();
            if (_current_block == nullptr) {
                // should not happen - there's a sanity check above
                internal_error();
                semaphore->give();
                return false;
            }
        }
        uint16_t remaining_to_copy = size - copied;
        uint16_t _curr_remaining = remaining_space_in_current_block();
        uint16_t to_copy = (remaining_to_copy > _curr_remaining) ? _curr_remaining : remaining_to_copy;
        memcpy(&(_current_block->buf[_latest_block_len]), &((const uint8_t *)pBuffer)[copied], to_copy);
        copied += to_copy;
        _latest_block_len += to_copy;
        if (_latest_block_len == MAVLINK_MSG_REMOTE_LOG_DATA_BLOCK_FIELD_DATA_LEN) {
            //block full, mark it to be sent:
            enqueue_block(_blocks_pending, _current_block);
            _current_block = next_block();
        }
    }

    semaphore->give();

    return true;
}
Пример #4
0
/* The size of the heap, not including the last block if it's free */
CELL heap_size(F_HEAP *heap)
{
	F_BLOCK *scan = first_block(heap);

	while(next_block(heap,scan) != NULL)
		scan = next_block(heap,scan);

	/* this is the last block in the heap, and it is free */
	if(scan->status == B_FREE)
		return (CELL)scan - heap->segment->start;
	/* otherwise the last block is allocated */
	else
		return heap->segment->size;
}
Пример #5
0
/* The size of the heap, not including the last block if it's free */
cell heap::heap_size()
{
	heap_block *scan = first_block();

	while(next_block(scan) != NULL)
		scan = next_block(scan);

	/* this is the last block in the heap, and it is free */
	if(scan->type() == FREE_BLOCK_TYPE)
		return (cell)scan - seg->start;
	/* otherwise the last block is allocated */
	else
		return seg->size;
}
Пример #6
0
/**
 * Scan a region of memory and mark any items in the used list appropriately.
 * Both arguments should be word aligned.
 */
void mark_from_region(void *start_ptr, void *end_ptr)
{
	header_t 	*block_ptr;
	void	 	*current_ptr;
	
	//Iterate word-wise throught the memory
	for(current_ptr = start_ptr; current_ptr < end_ptr; current_ptr += sizeof(void*))
	{
		ptr_int value;
		
		value = *(ptr_int*)current_ptr;
		
		//Iterate thought used memory blocks
		block_ptr = usedptr;
		do
		{
			//If pointer value point somewhere into this allocate block
			if((ptr_int)start_of_block(block_ptr) <= value
				&& (ptr_int)end_of_block(block_ptr) > value)
			{
				tag(block_ptr);
				break;
			}
			block_ptr = next_block(block_ptr);
		}while(block_ptr != NULL);
	}
}
Пример #7
0
/* Compute total sum of sizes of free blocks, and size of largest free block */
void heap_usage(F_HEAP *heap, CELL *used, CELL *total_free, CELL *max_free)
{
	*used = 0;
	*total_free = 0;
	*max_free = 0;

	F_BLOCK *scan = first_block(heap);

	while(scan)
	{
		switch(scan->status)
		{
		case B_ALLOCATED:
			*used += scan->size;
			break;
		case B_FREE:
			*total_free += scan->size;
			if(scan->size > *max_free)
				*max_free = scan->size;
			break;
		default:
			critical_error("Invalid scan->status",(CELL)scan);
		}

		scan = next_block(heap,scan);
	}
}
Пример #8
0
/* After code GC, all referenced code blocks have status set to B_MARKED, so any
which are allocated and not marked can be reclaimed. */
void free_unmarked(F_HEAP *heap)
{
	F_BLOCK *prev = NULL;
	F_BLOCK *scan = first_block(heap);

	while(scan)
	{
		switch(scan->status)
		{
		case B_ALLOCATED:
			if(prev && prev->status == B_FREE)
				prev->size += scan->size;
			else
			{
				scan->status = B_FREE;
				prev = scan;
			}
			break;
		case B_FREE:
			if(prev && prev->status == B_FREE)
				prev->size += scan->size;
			break;
		case B_MARKED:
			scan->status = B_ALLOCATED;
			prev = scan;
			break;
		default:
			critical_error("Invalid scan->status",(CELL)scan);
		}

		scan = next_block(heap,scan);
	}

	build_free_list(heap,heap->segment->size);
}
Пример #9
0
/*** function free_block ***
Deallocate a target block.
Input:
# Heap heap : The target heap
# char** input : The users command-line input
  input[0] : The name of this program
  input[1] : The number of the block which will be deallocated.
Returns: void
*/
void free_block(char*heap, char** input) {
	int blockDelete = atoi(input[1]);
	size_t blockID;
	size_t size;
	bool allocated;
	char *point = heap;
  size_t totalSize = 0;
  if(blockDelete <= 0) {
    puts("Invalid block number.");
    return;
  }
	read_block((header_t*) point, &size, &allocated, &blockID);
	while(blockID != blockDelete){
	  point = (char*) next_block((header_t*) point);
	  read_block((header_t*) point, &size, &allocated, &blockID);
    totalSize += size;
	  if (blockID == 0 || totalSize >= 400){
			puts("Invalid block number.");
			return;
	  }
  }
	if (blockID == blockDelete){
		if (!allocated){
			puts("Invalid block number.");
			return;
		}
		*(header_t*)point = *(header_t*)point & ~0x8000;
	}
}
Пример #10
0
/*** function print_blocklist ***
Print a list of all blocks in the heap.
Input:
# Heap heap : The target heap
# char** input : The users command-line input
  input[0] : The name of this program
Returns: void
*/
void print_blocklist(char*heap, char** input) {
  size_t size; // The size of a single block.
  size_t blockID;
  bool allocated; // The allocation status of a single block.
  char* start = heap; // The starting address of a single block.
  char* end; // The ending address of a single block
  size_t totalSize = 0; // The total amount of blocks we have examined.

  // printf("Size\tAllocated\tStart\tEnd\t\n");
  printf("%-7s%-12s%-16s%-16s\n", "Size", "Allocated", "Start", "End");

  // Loop through the blocks
  while(*(header_t*)start) { // && blockID !=0
    // Read in the target block.
    read_block((header_t*) start, &size, &allocated, &blockID);
    // Loop until we are out of the bounds of our heap. (400 blocks).
    totalSize += size;
    if(totalSize >= 400) {
      break;
    }
    // Point to it's end.
    end = start + size - 1;
    // Print it's information to stdout.
    printf("%-7ld%-12s%-16p%-16p\n", size, allocated == true ? "yes" : "no", start, end);
    // Advance to the next block.
    start = (char*) next_block((header_t*) start);
  }
}
Пример #11
0
/* Compute total sum of sizes of free blocks, and size of largest free block */
void heap::heap_usage(cell *used, cell *total_free, cell *max_free)
{
	*used = 0;
	*total_free = 0;
	*max_free = 0;

	heap_block *scan = first_block();

	while(scan)
	{
		switch(scan->status)
		{
		case B_ALLOCATED:
			*used += scan->size;
			break;
		case B_FREE:
			*total_free += scan->size;
			if(scan->size > *max_free)
				*max_free = scan->size;
			break;
		default:
			myvm->critical_error("Invalid scan->status",(cell)scan);
		}

		scan = next_block(scan);
	}
}
/* Write a block of data at current offset */
bool DataFlash_MAVLink::WriteBlock(const void *pBuffer, uint16_t size)
{   
    if (!_initialised || !_sending_to_client || !_writes_enabled) {
        return false;
    }

    if (! WriteBlockCheckPrefaceMessages()) {
        return false;
    }

    if (bufferspace_available() < size) {
        if (_startup_messagewriter->finished()) {
            // do not count the startup packets as being dropped...
            dropped++;
        }
        return false;
    }

    uint16_t copied = 0;

    while (copied < size) {
        if (_current_block == NULL) {
            _current_block = next_block();
            if (_current_block == NULL) {
                // should not happen - there's a sanity check above
                internal_error();
                return false;
            }
        }
        uint16_t remaining_to_copy = size - copied;
        uint16_t _curr_remaining = remaining_space_in_current_block();
        uint16_t to_copy = (remaining_to_copy > _curr_remaining) ? _curr_remaining : remaining_to_copy;
        memcpy(&(_current_block->buf[_latest_block_len]), &((const uint8_t *)pBuffer)[copied], to_copy);
        copied += to_copy;
        _latest_block_len += to_copy;
        if (_latest_block_len == MAVLINK_MSG_REMOTE_LOG_DATA_BLOCK_FIELD_DATA_LEN) {
            //block full, mark it to be sent:
            enqueue_block(_blocks_pending, _current_block);
            _current_block = next_block();
        }
    }

    if (!_writing_preface_messages) {
        // push_log_blocks();
    }
    return true;
}
Пример #13
0
/**
 * Scans the heap for active pointers and marks ones that points somewhere
 */
void mark_from_heap(void)
{
	header_t *current_ptr;
	
	for(current_ptr = usedptr; current_ptr != NULL; current_ptr = next_block(current_ptr))
	{
		mark_from_region(start_of_block(current_ptr), end_of_block(current_ptr));
	}
}
Пример #14
0
void heap::clear_mark_bits()
{
	heap_block *scan = first_block();

	while(scan)
	{
		scan->set_marked_p(false);
		scan = next_block(scan);
	}
}
Пример #15
0
/*
 * free - free a allocated block
 */
void free(void *bp) {
    if (bp == NULL) {
        return;
    }
    dbg_printf("want to free %d size block in address 0x%lx\n", (int)block_size(bp), (long)bp);
    print_heap();
    if (block_alloc(bp) == 0) {
        return;
    }
    if (heap_head == NULL) {
        mm_init();
    }
    mark(bp, block_size(bp), block_prev_alloc(bp), 0);
    mark(next_block(bp), block_size(next_block(bp)), 0, block_alloc(next_block(bp)));
    insert_to_list(bp);
    bp = coalesce(bp);
    dbg_printf("want return from free %d size block in address 0x%lx\n", (int)block_size(bp), (long)bp);
    print_heap();
}
Пример #16
0
/* Apply a function to every code block */
void iterate_code_heap(CODE_HEAP_ITERATOR iter)
{
	F_BLOCK *scan = first_block(&code_heap);

	while(scan)
	{
		if(scan->status != B_FREE)
			iterate_code_heap_step(block_to_compiled(scan),iter);
		scan = next_block(&code_heap,scan);
	}
}
Пример #17
0
/*
 * place - transform a free block to an allocated block,
 * then delete old free block from its free list
 * and insert the rest part to the corresponding free list
 */
static void place(void *bp, size_t alloc_block_size) {
    size_t size;
    delete_from_list(bp);
    size = block_size(bp);
    dbg_printf("want to place a %d size allocated block from a %d size free block\n", (int)alloc_block_size, (int)size);
    if (size - alloc_block_size >= 4 * WSIZE) {
        /* have rest part for a new free block */
        if (last_block == bp) {
            last_block = bp + alloc_block_size;
        }
        mark(bp, alloc_block_size, block_prev_alloc(bp), 1);
        bp += alloc_block_size;
        mark(bp, size - alloc_block_size, 1, 0);
        insert_to_list(bp);
    } else {
        /* have no rest part for a new free block */
        mark(bp, size, block_prev_alloc(bp), 1);
        mark(next_block(bp), block_size(next_block(bp)), 1, block_alloc(next_block(bp)));
    }
}
Пример #18
0
/* If in the middle of code GC, we have to grow the heap, data GC restarts from
scratch, so we have to unmark any marked blocks. */
void heap::unmark_marked()
{
	heap_block *scan = first_block();

	while(scan)
	{
		if(scan->status == B_MARKED)
			scan->status = B_ALLOCATED;

		scan = next_block(scan);
	}
}
Пример #19
0
/* If in the middle of code GC, we have to grow the heap, GC restarts from
scratch, so we have to unmark any marked blocks. */
void unmark_marked(F_HEAP *heap)
{
	F_BLOCK *scan = first_block(heap);

	while(scan)
	{
		if(scan->status == B_MARKED)
			scan->status = B_ALLOCATED;

		scan = next_block(heap,scan);
	}
}
Пример #20
0
/* Called after reading the code heap from the image file, and after code GC.

In the former case, we must add a large free block from compiling.base + size to
compiling.limit. */
void build_free_list(F_HEAP *heap, CELL size)
{
	F_BLOCK *prev = NULL;
	F_BLOCK *prev_free = NULL;
	F_BLOCK *scan = first_block(heap);
	F_BLOCK *end = (F_BLOCK *)(heap->segment->start + size);

	/* Add all free blocks to the free list */
	while(scan && scan < end)
	{
		switch(scan->status)
		{
		case B_FREE:
			update_free_list(heap,prev_free,scan);
			prev_free = scan;
			break;
		case B_ALLOCATED:
			break;
		default:
			critical_error("Invalid scan->status",(CELL)scan);
			break;
		}

		prev = scan;
		scan = next_block(heap,scan);
	}

	/* If there is room at the end of the heap, add a free block. This
	branch is only taken after loading a new image, not after code GC */
	if((CELL)(end + 1) <= heap->segment->end)
	{
		end->status = B_FREE;
		end->next_free = NULL;
		end->size = heap->segment->end - (CELL)end;

		/* add final free block */
		update_free_list(heap,prev_free,end);
	}
	/* This branch is taken if the newly loaded image fits exactly, or
	after code GC */
	else
	{
		/* even if there's no room at the end of the heap for a new
		free block, we might have to jigger it up by a few bytes in
		case prev + prev->size */
		if(prev)
			prev->size = heap->segment->end - (CELL)prev;

		/* this is the last free block */
		update_free_list(heap,prev_free,NULL);
	}

}
Пример #21
0
static void print_heap() {
    int i, block_count;
    unsigned *list_p;
    void *bp;
    size_t size, alloc;
    if (DEBUG_CHECKHEAP) {
        printf("\n----- arrays -----\n");
        list_p = (unsigned *)heap_head;
        for (i = 0; i <= 4; i++) {
            printf("0x%lx:  [%d, %d] -> %x\n", (long)list_p, i + 4, i + 4, (unsigned)*list_p);
            list_p++;
        }
        for (; i < ARRAYSIZE; i++) {
            printf("0x%lx:  [%d, %d] -> %x\n", (long)list_p, (1 << (i - 2)) + 1, 1 << (i - 1), (unsigned)*list_p);
            list_p++;
        }
        printf("----- blocks -----\n");
        bp = data_head + 4 * WSIZE;
        size = block_size(bp);
        alloc = block_alloc(bp);
        block_count = 0;
        while (!size == 0) {
            printf("\n----- block %d -----\n", block_count);
            block_count++;
            printf("bp: 0x%lx\n", (long)bp);
            printf("--- header ---\n");
            printf("size:  %d\n", (int)size);
            printf("prev alloc: %d\n", (int)block_prev_alloc(bp));
            printf("alloc: %d\n", (int)alloc);
            printf("---  data  ---\n");
            if (alloc == 0) { // free block
                printf("- pointer -\n");
                printf("pred: 0x%lx -> 0x%x\n", (long)bp, *(unsigned *)bp);
                printf("succ: 0x%lx -> 0x%x\n", (long)(bp + WSIZE), *((unsigned *)bp + 1));
            } else { // allocated block
                /*for (i = 0; i < size - DSIZE; i += WSIZE) {
                    printf("data[%d] = %d\n", i / WSIZE, *((int *)(bp + i)));
                }*/
                printf("data[%d~%d]\n", 0, (int)size / WSIZE - 2);
            }
            /*
            printf("--- footer ---\n");
            printf("size:  %d\n", (int)size);
            printf("prev alloc: %d\n", (int)block_prev_alloc(bp));
            printf("alloc: %d\n", (int)alloc);
            */
            bp = next_block(bp);
            size = block_size(bp);
            alloc = block_alloc(bp);
        }
        printf("last_block: %lx\n\n\n", (long)last_block);
    }
}
Пример #22
0
void heap::compact_heap()
{
	heap_block *scan = first_block();

	while(scan)
	{
		heap_block *next = next_block(scan);

		if(scan->type() != FREE_BLOCK_TYPE)
			memmove(forwarding[scan],scan,scan->size());
		scan = next;
	}
}
Пример #23
0
void heap::compact_heap(unordered_map<heap_block *,char *> &forwarding)
{
	heap_block *scan = first_block();

	while(scan)
	{
		heap_block *next = next_block(scan);

		if(scan->status == B_ALLOCATED)
			memmove(forwarding[scan],scan,scan->size);
		scan = next;
	}
}
Пример #24
0
void compact_heap(F_HEAP *heap)
{
	F_BLOCK *scan = first_block(heap);

	while(scan)
	{
		F_BLOCK *next = next_block(heap,scan);

		if(scan->status == B_ALLOCATED && scan != scan->forwarding)
			memcpy(scan->forwarding,scan,scan->size);
		scan = next;
	}
}
Пример #25
0
/**
 * Retrieves from the list first block of fitting size
 * @arg list_ptr pointer to the start pointer of a list
 * @arg size minimum searched size
 */
header_t *first_fit(header_t **list_ptr, size_t size)
{
	header_t *previous_ptr = NULL, *current_ptr;
	
	for(current_ptr = *list_ptr; current_ptr != NULL; current_ptr = next_block(current_ptr))
	{
		if(available_size(current_ptr) >= size)
			break;
		previous_ptr = current_ptr;
	}
	
	return remove_from_list(list_ptr, previous_ptr, current_ptr);
}
Пример #26
0
/* Called after reading the code heap from the image file, and after code GC.

In the former case, we must add a large free block from compiling.base + size to
compiling.limit. */
void heap::build_free_list(cell size)
{
	heap_block *prev = NULL;

	clear_free_list();

	size = (size + block_size_increment - 1) & ~(block_size_increment - 1);

	heap_block *scan = first_block();
	free_heap_block *end = (free_heap_block *)(seg->start + size);

	/* Add all free blocks to the free list */
	while(scan && scan < (heap_block *)end)
	{
		switch(scan->status)
		{
		case B_FREE:
			add_to_free_list((free_heap_block *)scan);
			break;
		case B_ALLOCATED:
			break;
		default:
			myvm->critical_error("Invalid scan->status",(cell)scan);
			break;
		}

		prev = scan;
		scan = next_block(scan);
	}

	/* If there is room at the end of the heap, add a free block. This
	branch is only taken after loading a new image, not after code GC */
	if((cell)(end + 1) <= seg->end)
	{
		end->status = B_FREE;
		end->size = seg->end - (cell)end;

		/* add final free block */
		add_to_free_list(end);
	}
	/* This branch is taken if the newly loaded image fits exactly, or
	after code GC */
	else
	{
		/* even if there's no room at the end of the heap for a new
		free block, we might have to jigger it up by a few bytes in
		case prev + prev->size */
		if(prev) prev->size = seg->end - (cell)prev;
	}

}
Пример #27
0
/**
 * Appends new block to end of the list
 * @arg list_ptr pointer to the start pointer of a list
 * @arg new_ptr pointer to the new block of memory added
 */
void add_to_list(header_t **list_ptr, header_t *new_ptr)
{
	header_t *current_ptr, *previous_ptr = NULL;
	
	for(current_ptr = *list_ptr; current_ptr != NULL; current_ptr = next_block(current_ptr))
	{
		previous_ptr = current_ptr;
	}
	
	if(previous_ptr == NULL)
		*list_ptr = new_ptr;
	else
		previous_ptr->next = new_ptr;
	
	new_ptr->next = NULL;
}
Пример #28
0
/* Compute where each block is going to go, after compaction */
cell heap::compute_heap_forwarding()
{
	heap_block *scan = first_block();
	char *address = (char *)first_block();

	while(scan)
	{
		if(scan->type() != FREE_BLOCK_TYPE)
		{
			forwarding[scan] = address;
			address += scan->size();
		}
		scan = next_block(scan);
	}

	return (cell)address - seg->start;
}
Пример #29
0
/*
 * extend_heap - extend heap with a new free block and return its block pointer
 */
static void *extend_heap(size_t size) {
    void *bp;
    dbg_printf("want to extend heap by %d size\n", (int)size);
    bp = mem_sbrk(size);
    if (bp == (void *)-1) {
        return NULL;
    }
    if (last_block == NULL) {
        last_block = bp;
        mark(bp, size, 1, 0);
    } else {
        mark(bp, size, block_alloc(last_block), 0);
        last_block = bp;
    }
    PUT(HEAD(next_block(bp)), PACK(0, 0, 1)); /* set new epilogue */
    insert_to_list(bp);
    bp = coalesce(bp);
    return bp;
}
Пример #30
0
/* Called after reading the code heap from the image file, and after code GC.

In the former case, we must add a large free block from compiling.base + size to
compiling.limit. */
void heap::build_free_list(cell size)
{
	heap_block *prev = NULL;

	clear_free_list();

	size = (size + block_size_increment - 1) & ~(block_size_increment - 1);

	heap_block *scan = first_block();
	free_heap_block *end = (free_heap_block *)(seg->start + size);

	/* Add all free blocks to the free list */
	while(scan && scan < (heap_block *)end)
	{
		if(scan->type() == FREE_BLOCK_TYPE)
			add_to_free_list((free_heap_block *)scan);

		prev = scan;
		scan = next_block(scan);
	}

	/* If there is room at the end of the heap, add a free block. This
	branch is only taken after loading a new image, not after code GC */
	if((cell)(end + 1) <= seg->end)
	{
		end->set_marked_p(false);
		end->set_type(FREE_BLOCK_TYPE);
		end->set_size(seg->end - (cell)end);

		/* add final free block */
		add_to_free_list(end);
	}
	/* This branch is taken if the newly loaded image fits exactly, or
	after code GC */
	else
	{
		/* even if there's no room at the end of the heap for a new
		free block, we might have to jigger it up by a few bytes in
		case prev + prev->size */
		if(prev) prev->set_size(seg->end - (cell)prev);
	}

}