Ejemplo n.º 1
0
Archivo: pass2.c Proyecto: bihai/xchain
/*
 * final_output_flush() flushes the last part of the last page of the object
 * file if it does not round out to exactly a page.
 */
static
void
final_output_flush(void)
{ 
    struct block *block;
    unsigned long write_offset, write_size;
    kern_return_t r;

#ifdef DEBUG
	/* The compiler "warning: `write_offset' may be used uninitialized in */
	/* this function" can safely be ignored */
	write_offset = 0;
	if((debug & (1 << 11)) || (debug & (1 << 10))){
	    print("final_output_flush block_list:\n");
	    print_block_list();
	}
#endif /* DEBUG */

	write_size = 0;
	block = output_blocks;
	if(block != NULL){
	    if(block->offset != 0)
		fatal("internal error: first block not at offset 0");
	    if(block->written_size != 0){
		if(block->written_offset != 0)
		    fatal("internal error: first block written_offset not 0");
		write_offset = block->written_size;
		write_size = block->size - block->written_size;
	    }
	    else{
		write_offset = block->offset;
		write_size = block->size;
	    }
	    if(block->next != NULL)
		fatal("internal error: more than one block in final list");
	}
	if(write_size != 0){
#ifdef DEBUG
	    if((debug & (1 << 11)) || (debug & (1 << 10)))
		print(" writing (write_offset = %lu write_size = %lu)\n",
		       write_offset, write_size);
#endif /* DEBUG */
	    lseek(fd, write_offset, L_SET);
	    if(write(fd, output_addr + write_offset, write_size) !=
	       (int)write_size)
		system_fatal("can't write to output file");
	    if((r = vm_deallocate(mach_task_self(), (vm_address_t)(output_addr +
				  write_offset), write_size)) != KERN_SUCCESS)
		mach_fatal(r, "can't vm_deallocate() buffer for output file");
	}
}
Ejemplo n.º 2
0
int main(int argc, char *argv[]) {

  int i = 0, j = 0;
  int cnt = 0;
  int target = 0, rsize = 0;
  int tsize = 0;

  /* Error Checking */
  if (argc < 2) {
    printf("Usage: %s [-b or -w] input_file\n", argv[0]);
    exit(1);
  }

  load(argv[argc-1]);


  while(cnt != argc-1){
    if(strcmp(argv[cnt], "-b") == 0){
      fit_flag = BEST_FIT;
    }
    else if(strcmp(argv[cnt], "-w") == 0) {
      fit_flag = WORST_FIT;
    } else if(strcmp(argv[cnt], "-np") == 0) {
      print_flag =0;
    }

    cnt++;
  }

  for(i = 0 ; i < query_cnt ; i++) {

    switch(query_list[i].type) {
      case 'm':
      alloc_list[j] = m_malloc(strlen(query_list[i].val) + 1);
      strcpy(alloc_list[j], query_list[i].val);
      j++;
      break;
      case 'f':
      target = atoi(query_list[i].val);
      m_free(alloc_list[target]);
      break;
      case 'a':
      sscanf(query_list[i].val, "%d %d", &target, &rsize);
      tsize = strlen(alloc_list[target]) + rsize;
      m_realloc(alloc_list[target], tsize);
      break;
      case 'd':
      sscanf(query_list[i].val, "%d %d", &target, &rsize);
      tsize = strlen(alloc_list[target]) - rsize;
      m_realloc(alloc_list[target], tsize);
      *(alloc_list[target] + tsize) = '\0';
      break;
      case 'e':
      alloc_list[j++] = m_malloc(atoi(query_list[i].val));
      break;
    }

    print_block_list();
  }

  return 0;
}
Ejemplo n.º 3
0
Archivo: pass2.c Proyecto: bihai/xchain
/*
 * output_flush() takes an offset and a size of part of the output file, known
 * in the comments as the new area, and causes any fully flushed pages to be
 * written to the output file the new area in combination with previous areas
 * creates.  The data structure output_blocks has ordered blocks of areas that
 * have been flushed which are maintained by this routine.  Any area can only
 * be flushed once and an error will result is the new area overlaps with a
 * previously flushed area.
 *
 * The goal of this is to again minimize the number of dirty pages the link
 * editor has and hopfully improve performance in a memory starved system and
 * to prevent these pages to be written to the swap area when they could just be
 * written to the output file (if only external pagers worked well ...).
 */
extern
void
output_flush(
unsigned long offset,
unsigned long size)
{ 
    unsigned long write_offset, write_size;
    struct block **p, *block, *before, *after;
    kern_return_t r;

	if(flush == FALSE)
	    return;

/*
if(offset == 588824 && size != 0)
printf("in output_flush() offset = %lu size = %lu\n", offset, size);
*/

	if(offset + size > output_size)
	    fatal("internal error: output_flush(offset = %lu, size = %lu) out "
		  "of range for output_size = %lu", offset, size, output_size);

#ifdef DEBUG
	if(debug & (1 << 12))
	    print_block_list();
	if(debug & (1 << 11))
	    print("output_flush(offset = %lu, size %lu)", offset, size);
#endif /* DEBUG */

	if(size == 0){
#ifdef DEBUG
	if(debug & (1 << 11))
	    print("\n");
#endif /* DEBUG */
	    return;
	}

	/*
	 * Search through the ordered output blocks to find the block before the
	 * new area and after the new area if any exist.
	 */
	before = NULL;
	after = NULL;
	p = &(output_blocks);
	while(*p){
	    block = *p;
	    if(offset < block->offset){
		after = block;
		break;
	    }
	    else{
		before = block;
	    }
	    p = &(block->next);
	}

	/*
	 * Check for overlap of the new area with the block before and after the
	 * new area if there are such blocks.
	 */
	if(before != NULL){
	    if(before->offset + before->size > offset){
		warning("internal error: output_flush(offset = %lu, size = %lu) "
		      "overlaps with flushed block(offset = %lu, size = %lu)",
		      offset, size, before->offset, before->size);
		printf("calling abort()\n");	
		abort();
	    }
	}
	if(after != NULL){
	    if(offset + size > after->offset){
		warning("internal error: output_flush(offset = %lu, size = %lu) "
		      "overlaps with flushed block(offset = %lu, size = %lu)",
		      offset, size, after->offset, after->size);
		printf("calling abort()\n");	
		abort();
	    }
	}

	/*
	 * Now see how the new area fits in with the blocks before and after it
	 * (that is does it touch both, one or the other or neither blocks).
	 * For each case first the offset and size to write (write_offset and
	 * write_size) are set for the area of full pages that can now be
	 * written from the block.  Then the area written in the block
	 * (->written_offset and ->written_size) are set to reflect the total
	 * area in the block now written.  Then offset and size the block
	 * refers to (->offset and ->size) are set to total area of the block.
	 * Finally the links to others blocks in the list are adjusted if a
	 * block is added or removed.
	 *
	 * See if there is a block before the new area and the new area
	 * starts at the end of that block.
	 */
	if(before != NULL && before->offset + before->size == offset){
	    /*
	     * See if there is also a block after the new area and the new area
	     * ends at the start of that block.
	     */
	    if(after != NULL && offset + size == after->offset){
		/*
		 * This is the case where the new area exactly fill the area
		 * between two existing blocks.  The total area is folded into
		 * the block before the new area and the block after the new
		 * area is removed from the list.
		 */
		if(before->offset == 0 && before->written_size == 0){
		    write_offset = 0;
		    before->written_offset = 0;
		}
		else
		    write_offset =before->written_offset + before->written_size;
		if(after->written_size == 0)
		    write_size = trunc(after->offset + after->size -
				       write_offset, host_pagesize);
		else
		    write_size = trunc(after->written_offset - write_offset,
				       host_pagesize);
		if(write_size != 0){
		    before->written_size += write_size;
		}
		if(after->written_size != 0)
		    before->written_size += after->written_size;
		before->size += size + after->size;

		/* remove the block after the new area */
		before->next = after->next;
		remove_block(after);
	    }
	    else{
		/*
		 * This is the case where the new area starts at the end of the
		 * block just before it but does not end where the block after
		 * it (if any) starts.  The new area is folded into the block
		 * before the new area.
		 */
		write_offset = before->written_offset + before->written_size;
		write_size = trunc(offset + size - write_offset, host_pagesize);
		if(write_size != 0)
		    before->written_size += write_size;
		before->size += size;
	    }
	}
	/*
	 * See if the new area and the new area ends at the start of the block
	 * after it (if any).
	 */
	else if(after != NULL && offset + size == after->offset){
	    /*
	     * This is the case where the new area ends at the begining of the
	     * block just after it but does not start where the block before it.
	     * (if any) ends.  The new area is folded into this block after the
	     * new area.
	     */
	    write_offset = round(offset, host_pagesize);
	    if(after->written_size == 0)
		write_size = trunc(after->offset + after->size - write_offset,
				   host_pagesize);
	    else
		write_size = trunc(after->written_offset - write_offset,
				   host_pagesize);
	    if(write_size != 0){
		after->written_offset = write_offset;
		after->written_size += write_size;
	    }
	    else if(write_offset != after->written_offset){
		after->written_offset = write_offset;
	    }
	    after->offset = offset;
	    after->size += size;
	}
	else{
	    /*
	     * This is the case where the new area neither starts at the end of
	     * the block just before it (if any) or ends where the block after
	     * it (if any) starts.  A new block is created and the new area is
	     * is placed in it.
	     */
	    write_offset = round(offset, host_pagesize);
	    write_size = trunc(offset + size - write_offset, host_pagesize);
	    block = get_block();
	    block->offset = offset;
	    block->size = size;
	    block->written_offset = write_offset;
	    block->written_size = write_size;
	    /*
	     * Insert this block in the ordered list in the correct place.
	     */
	    if(before != NULL){
		block->next = before->next;
		before->next = block;
	    }
	    else{
		block->next = output_blocks;
		output_blocks = block;
	    }
	}

	/*
	 * Now if there are full pages to write write them to the output file.
	 */
	if(write_size != 0){
#ifdef DEBUG
	if((debug & (1 << 11)) || (debug & (1 << 10)))
	    print(" writing (write_offset = %lu write_size = %lu)\n",
		   write_offset, write_size);
#endif /* DEBUG */
	    lseek(fd, write_offset, L_SET);
	    if(write(fd, output_addr + write_offset, write_size) !=
	       (int)write_size)
		system_fatal("can't write to output file");
	    if((r = vm_deallocate(mach_task_self(), (vm_address_t)(output_addr +
				  write_offset), write_size)) != KERN_SUCCESS)
		mach_fatal(r, "can't vm_deallocate() buffer for output file");
	}
#ifdef DEBUG
	else{
	    if(debug & (1 << 11))
		print(" no write\n");
	}
#endif /* DEBUG */
}
Ejemplo n.º 4
0
// Fault any disk block that is read in to memory by
// loading it from disk.
static void
bc_pgfault(struct UTrapframe *utf)
{
	void *addr = (void *) utf->utf_fault_va;
	uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE;
	int r;

	// Check that the fault was within the block cache region
	if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE))
		panic("page fault in FS: eip %08x, va %08x, err %04x",
		      utf->utf_eip, addr, utf->utf_err);

	// Sanity check the block number.
	if (super && blockno >= super->s_nblocks)
		panic("reading non-existent block %08x\n", blockno);

	// Allocate a page in the disk map region, read the contents
	// of the block from the disk into that page.
	// Hint: first round addr to page boundary. fs/ide.c has code to read
	// the disk.
	//
	// LAB 5: you code here:
    addr = ROUNDDOWN(addr, PGSIZE);
    update_blk_count();
    update_time_stamp();
    print_block_list();
    if (curr_disk_size == MAXFILECACHE) //no memory for disk mapping, have to evict
    {
            uint32_t i, min_blk = 0, min_count = 0xffffffff;
            for (i=0; i<MAXBLK; ++i)
            if (plist[i].valid && plist[i].tstamp<min_count && i!=1) 
            //use LRU policy to evict a block
            {
                    assert(i!=blockno);
                    min_blk = i;
                    min_count = plist[i].tstamp;
            }
            cprintf("evict block at %x, used %d times, last used at time %x, load block at %x\n",
                            diskaddr(min_blk), plist[min_blk].count, plist[min_blk].tstamp, addr);
            flush_block(diskaddr(min_blk));
            curr_disk_size -=PGSIZE;
            plist[min_blk].valid =0;
            sys_page_unmap(0, diskaddr(min_blk));
    } else 
    {
            cprintf("load block at %x, no eviction\n", addr);
    }
    cprintf("total miss: %d\n", timestamp);
    curr_disk_size += PGSIZE;
    if ((r = sys_page_alloc(0, addr, PTE_SYSCALL)) <0) 
            panic("in bc_pgfault, sys_page_alloc: %e", r);
    if ((r = ide_read(blockno * BLKSECTS, addr, BLKSECTS)) < 0)
            panic("in bc_pgfault, ideread: %e", r);
	// Clear the dirty bit for the disk block page since we just read the
	// block from disk
	if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0)
		panic("in bc_pgfault, sys_page_map: %e", r);
    plist[blockno].valid = 1;
    plist[blockno].count = 0;
    plist[blockno].tstamp = ++timestamp;
	// Check that the block we read was allocated. (exercise for
	// the reader: why do we do this *after* reading the block
	// in?)
	if (bitmap && block_is_free(blockno))
		panic("reading free block %08x\n", blockno);
    sys_ptea_flush();
}