Пример #1
0
/* Called in page_alloc ONLY at the moment.
 * This method will page available IF NEEDED - i.e. if there are less than 10 free
 * pages on the system, we'll start swapping. If not, we simply return.
 */
static
void
make_page_available()
{
	//KASSERT(spinlock_do_i_hold(&stealmem_lock));
	// DEBUG(DB_SWAP, "Free Pages: %d\n",free_pages);	
	if(free_pages <= 10) {
		struct thread *cur = curthread;
		(void)cur;
		// DEBUG(DB_SWAP, "Making page available\n");
		//DEBUG(DB_SWAP, "Start Swap: %d\n",free_pages);	
		//DEBUG(DB_SWAP, "\nStart Swapping\n");	
		int rr_page = get_a_dirty_page_index(0);
		if(rr_page == -1)
		{
			return;
		}
		//KASSERT(spinlock_do_i_hold(&stealmem_lock));
		KASSERT(core_map[rr_page].state == SWAPPINGOUT);
		// DEBUG(DB_SWAP, "SWOs%d\n",rr_page);
		swapout_page(&core_map[rr_page]);
		// KASSERT(spinlock_do_i_hold(&stealmem_lock));
		// DEBUG(DB_SWAP, "Starting Eviction...%d\n",rr_page);
		evict_page(&core_map[rr_page]);
		// KASSERT(spinlock_do_i_hold(&stealmem_lock));
		//DEBUG(DB_SWAP, "Evicted %d\n",rr_page);
	}
	// KASSERT(spinlock_do_i_hold(&stealmem_lock));
}
Пример #2
0
/* Tries to allocate and lock a frame for PAGE.
 Returns the frame if successful, false on failure. */
struct frame *
frame_alloc_and_lock(struct page *page) {
	struct frame *new_frame;
	uint8_t *kpage;
	while (true) {
		kpage = palloc_get_page(PAL_USER);
		if (kpage != NULL) {
			lock_acquire(&ftable_lock);
			new_frame = (struct frame *) malloc(sizeof(struct frame));
			if (page->swap_flag != 1)
				page->swap_flag = 0;
			page->frame_holder_thread = thread_current();
			new_frame->page = page;
			new_frame->base = kpage;
			list_insert(list_end(&frame_list), &new_frame->frame_list_elem);
			// new_frame->page->swap_flag = 0;
			lock_release(&ftable_lock);
			break;
		} else {
			// lock_release(&ftable_lock);
			// PANIC("No free page available");
			// page eviction comes here
			// printf("\nEntered EVICT PAGE section");
			evict_page();
			// page->swap_flag = 1;
			// printf("\nExited EVICT PAGE section");
		}
	}
	return new_frame;
}
Пример #3
0
// creates a new entry in the page table
// If RAM is full. an entry is evicted to 
// make room for the current.
vAddr create_page(void){
	if(printing == 2){
		printf("Creating new page\n");
	}
	

	// Get the address of the next available empty non-locked page
	// Once a page is found, it is returned in the locked state
	vAddr new_vAddr = get_new_page_address();

	// If the page table is full, return an error
	if(new_vAddr == -1){
		if(printing){
			printf("Page Table full\n");
		}

		return -1;
	}


	// Initialize the new page
	init_page(&(page_table[new_vAddr]));

	// Find a pageframe in ram to give to it
	int temp = evict_page(ram);

	// Add the new page to this location
	// add_to_lowest(&(page_table[new_vAddr]),ram);

	page_table[new_vAddr].location = temp;
	page_table[new_vAddr].memlev = ram;
	page_table[new_vAddr].empty = 0;

	if(printing == 2){
		printf("Successfully created new page at %i\n", new_vAddr);
		printf("\n");
	}

	// Unlock page
	pthread_mutex_unlock(&(page_table[new_vAddr].lock));

	return new_vAddr;

}
Пример #4
0
int swap_out_page(void) {
	if (!swap_initialized) {
		int err = swap_init();
		if (err)
			return err;
	}

	struct page* p = find_swapout();

	if (p==NULL)
		panic("Could not find a page to swap out");
	
	spinlock_acquire(&p->pg_lock);
	
	if (p->is_dirty)
		write_out_page(p);

	evict_page(p);
	p->status = IN_SWAP;
	p->ram_addr = 31;
	
	spinlock_release(&p->pg_lock);
	return 0;
}
Пример #5
0
// Evict Page returns the location of the lowest open slot in the provided memory level
// If there are no open spots, it uses the paging algorithm to evict one page from the memlev
// and move it to the next one. 
int evict_page(Memlev memlev) {
	// printf("Trying to evict a page.\n");

	// Interate through the entire page table
	// If there is still room available in ram
	// find the lowest available location and return the data
	int i;
	int max_elements = 0;

	// This switch case determines the memory level the eviction is on
	// if the provided memlevel is "nul" or "hdd", not page can be 
	// evicted and an error value of -2 is returned.
	switch(memlev){
		case ram:
			// printf("Trying to evict page from ram\n");
			max_elements = MAXRAM;
			break;
		case ssd:
			// printf("Trying to evict page from ssd\n");
			max_elements = MAXSSD;
			break;
		case hdd:
			// printf("Trying to evict page from hdd\n");
			max_elements = MAXHDD;
			break;
		default:
			printf("Trying to evict page from the 'nul' level\n");
			return -2;
			break;
		break;
	}

	// This is the list of all the available pageframes in a memlev
	// 1 = taken, 0 = available
	int slots[max_elements];

	// Iterate through the entire page table, marking all the taken pageframes
	for(int i = 0; i < max_elements; i++){
		slots[i] = 0;
	}

	// Iterate through the entire page table, marking all the taken pageframes
	for(i = 0; i < MAXADDR; i++){
		if(page_table[i].memlev == memlev && page_table[i].empty == 0){
			slots[page_table[i].location] = 1;
		}
	}

	// Once all the take page frames are marked, see if any are still available
	for(i = 0; i < max_elements; i++){
		// If there is a pageframe available
		// update the location with the ram information and return it.
		if(slots[i] == 0){
			switch(memlev){
				case ram:
					// printf("Trying to lock ram slot %i\n", i);
					if(pthread_mutex_trylock(&(lock_ram[i])) == 0){
						// printf("Successfully locked ram slot %i\n", i);
						return i;
					}
					// printf("Failed to lock ram slot %i\n", i);
					break;
				case ssd:
					if(pthread_mutex_trylock(&(lock_ssd[i])) == 0){
						return i;
					}
					break;
				case hdd:
					if(pthread_mutex_trylock(&(lock_hdd[i])) == 0){
						return i;
					}
					break;
				break;
			}
		}
	}


	// If there are no spots in this memory level,
	// then we will have to move a page out
	// and into the higher memory level

	// Here we call evict on the next memory level
	// to find a place to move the evicted page
	// printf("'We need to go deeper'\n");
	int new_slot = evict_page(memlev + 1);

	if(new_slot < 0){
		printf("There is a serious problem\n");	
	}

	// We call our custom algorithm to find a page to evict
	vAddr temp_page = page_to_remove(memlev, type_r);

	// finally we move the content to the higher memory level
	switch(memlev) {
		case ram:
			write_to_memory(ssd, new_slot, read_from_memory(ram, page_table[temp_page].location));
			break;
		case ssd:
			write_to_memory(hdd, new_slot, read_from_memory(ssd, page_table[temp_page].location));
			break;
		break;
	}

	// update it's paging information to reflect the new position
	page_table[temp_page].memlev = memlev + 1;
	int result = page_table[temp_page].location;
	page_table[temp_page].location = new_slot;

	// Unlock the modified page
	pthread_mutex_unlock(&(page_table[temp_page].lock));

	// And return the newly opened pageframe
	return result;
}
Пример #6
0
// This method takes in a page address and content
// and tries to put the content in the desired page
// If the page is not in RAM, a page fault is generated and the page is moved into ram
// Error = 0, success
// Error = 1, desired page is outside page table range
// Error = 2, Requested page is empty
int store_value(vAddr address, content c) {
	if(printing == 2){
		printf("Storing value %i in page %i\n", c, address);
	}

	if((address > MAXADDR) || (address < 0)){
		if(printing == 2){
			printf("Page Fault: Tried to access an page outside range: %d\n",address);
		}
		return 1;
	}

	// return the result
	if(page_table[address].empty) {
		if(printing == 2){
			printf("Page Fault: Requested page is empty: %d\n",address);
		}
		return 2;
	}
	// Lock this page to prevent other threads from manipulating it
	pthread_mutex_lock(&(page_table[address].lock));

	// check if the desired page is in RAM
	if(page_table[address].memlev != ram) {
		if(printing == 2){
			printf("Page Fault: requested page not in RAM\n");
		}

		int new_location = evict_page(ram);

		write_to_memory(ram, new_location, read_from_memory(page_table[address].memlev, page_table[address].location));

		// Unlock the now free pageframe in the previous memory level
		switch(page_table[address].memlev){
			case ssd:
				pthread_mutex_unlock(&(lock_ssd[page_table[address].location]));
				break;
			case hdd:
				pthread_mutex_unlock(&(lock_hdd[page_table[address].location]));
				break;
			break;
		}

		// update the information for the page
		page_table[address].memlev = ram;
		page_table[address].location = new_location;
		page_table[address].referenced++;

		if(printing == 2){
			printf("Recovered from Page Fault: requested page not in RAM\n");
		}
	}

	// write the information to the ram location
	write_to_memory(ram, page_table[address].location, c);

	if(printing == 2){
		printf("\n");
	}

	// Unlock the page
	pthread_mutex_unlock(&(page_table[address].lock));

	return 0;
}
Пример #7
0
/* Called in page_nalloc ONLY at the moment.
 * This method will page available IF NEEDED - i.e. if there are less than 10 free
 * pages on the system, we'll start swapping. If not, we simply return. 
 */
static
void
make_pages_available(int npages, bool retry)
{
	/*
	//KASSERT(spinlock_do_i_hold(&stealmem_lock));
	// bool lock = get_coremap_lock();
	// DEBUG(DB_SWAP,"MPA:%d\n",npages);
	if(free_pages <= 10) {
		//Disable interrupts until we find the right number of pages. ->should be disabled in page_alloc()
		//int spl = splhigh();
		size_t rr_page = current_n_index;
		if(retry)
		{
			rr_page = 0;
		}
		bool blockStarted = false;
		int pagesFound = 0;
		int startingPage = 0;
		// DEBUG(DB_SWAP, "NPages:%d\n",npages);
		// DEBUG(DB_SWAP, "Page Count:%d\n",page_count);
		for(size_t i = rr_page;i < (size_t) page_count;i++)
		{
			// DEBUG(DB_SWAP, "Page: %d State: %d\n",i,core_map[i].state);
			page_state_t curState = core_map[i].state;
			if(!blockStarted && (curState == DIRTY || curState == FREE))
			{
				blockStarted = true;
				pagesFound = 1;
				startingPage = i;
			}
			else if(blockStarted && (curState != DIRTY && curState != FREE))
			{
				blockStarted = false;
				pagesFound = 0;
			}
			else if(blockStarted && (curState == DIRTY || curState == FREE))
			{
				pagesFound++;
			}
			if(pagesFound == npages)
			{
				//Mark the pages as SWAPPING OUT.
				for(int j = startingPage; j<startingPage + npages; j++)
				{
					KASSERT(core_map[j].state == DIRTY || core_map[j].state == FREE);
					if(core_map[j].state == DIRTY)
					{
						core_map[j].state = SWAPPINGOUT;
						//Update PTE to state PTE_SWAPPING
						struct page_table *pt = pgdir_walk(core_map[j].as,core_map[j].va,false);
						int pt_index = VA_TO_PT_INDEX(core_map[j].va);
						pt->table[pt_index] |= PTE_SWAPPING;
						// DEBUG(DB_SWAP, "%d\n",pt->table[pt_index]);
						//////////////////////////////////
					}
				}
				current_index = startingPage + npages + 1;
				//splx(spl);
				//Swap out the block of pages, now
				for(int j = startingPage; j<startingPage + npages; j++)
				{
					KASSERT(core_map[j].state == FREE || core_map[j].state == SWAPPINGOUT);
					// DEBUG(DB_SWAP,"SWOn%d-%d\n",j,npages);
					if(core_map[j].state == SWAPPINGOUT)
					{
						//KASSERT(spinlock_do_i_hold(&stealmem_lock));
						swapout_page(&core_map[j]);
						evict_page(&core_map[j]);	
					}
				}
				// release_coremap_lock(lock);
				return;
			}
		}
		//If we get here, we reached the end of memory. Try again ONCE.
		if(retry == 2)
		{
			DEBUG(DB_SWAP,"\n");
			for(size_t i = 0;i<page_count;i++)
			{
				//int spl = splhigh();
				DEBUG(DB_SWAP,"I:%d S:%d\n",i,core_map[i].state);
				//splx(spl);
			}

			panic("Couldn't swap a big enough chunk for npages!");
		}
		else
		{
			//splx(spl);
			make_pages_available(npages,1);
		}
	}
	*/
	// release_coremap_lock(lock);


	(void)npages;
	(void)retry;
	// Since we probably need a lot of pages, due to forking and such,
	// why not just flush all of memory?
	if(free_pages > 10)
	{
		return;
	}
	bool lock; 
	lock = get_coremap_lock();

	for (int i = 0; i < (int)page_count; i++) {
		int spl = splhigh();
		if(core_map[i].state == DIRTY) {
			KASSERT(core_map[i].state != SWAPPINGOUT);
			core_map[i].state = SWAPPINGOUT;
			//Update PTE to state PTE_SWAPPING
			struct page_table *pt = pgdir_walk(core_map[i].as,core_map[i].va,false);
			int pt_index = VA_TO_PT_INDEX(core_map[i].va);
			pt->table[pt_index] |= PTE_SWAPPING;
			splx(spl);
			// KASSERT(core_map[i].state != SWAPPINGOUT);
			swapout_page(&core_map[i]);
			evict_page(&core_map[i]);	
		}
		else
		{
			splx(spl);
		}
	}

	release_coremap_lock(lock);
}
Пример #8
0
int main(int argc, char *argv[]){
	
	FILE *fp;								// stimulus file handle
	char filename[50] = "stim.txt";			// stimulus file name, can be overwritten on cmdline
	 // if filename given on commandline use it otherwise use default filename
	if (argc == 2)	{strcpy(filename, argv[1]);}
	else			{strcpy(filename, "stim.txt");}
	
	int opt = 0;
	
	// parse the cmdline
	while ((opt = getopt(argc, argv, "i:p:")) != -1) {
		switch(opt) {
			case 'i':	strcpy(filename, optarg); break;
			case 'p':	available_pf = (u32) strtol(optarg,NULL,10);
						validate_pf_number(available_pf);
						break;
			case '?': 
						if (optopt == 'i'){
							printf("USAGE: -i <filename>\n\n");
							return -1;
						} else if (optopt == 'p') {
							printf("USAGE: -p <numpages>\n\n");
							return -1;
						} else {
							printf("Valid switches are:\n");
							printf("\t -i <input_filename>\n\t -p <numpages>\n\n");
							return -1;
						break;
						}
		}
	}
	
	// open the input file
	fp = fopen (filename,"r");
	if (NULL == fp){
		fprintf (stderr, "Failed to open input file. This is fatal!\n");
		exit(0);
	}
	//call function to allocate memory to PD
	init_PD();
	
	// loop through input file an feed commands to sim
	do {
		get_command(fp);
		if (strcmp(cmd, "-v") == MATCH) {
			printf("VMM Simulator Ver 0.1\n"); 
			exit(-1);
		}
		else if (strcmp(cmd, "w") == MATCH || strcmp(cmd, "r") == MATCH ) {
			// update read/wrote/access statistics
			num_accesses ++;
			if (strcmp(cmd, "w") == MATCH) {num_writes ++;}
			else                           {num_reads ++;}
			
			parse_addr(addr);
			if ( t_flag == 1 ){
				printf(" %s 0x%08X\n", cmd, addr);
			}
			if (is_PT_present(working_addr.PD_index) == 1) {
			    //check the user page present
				if(is_UP_present(working_addr.PD_index, working_addr.PT_index) == 1)
				{
					total_cycles += 20;               //if the address exist, it considers memory access
					//printf("get here few time\n");
				}
				else  //the PT exists but not the user page
				{
				   if (available_pf == used_pf)       // no pf avail then evict one page
						evict_page();
				   create_user_page(working_addr.PD_index, working_addr.PT_index,cmd);
				}
			}
			else   // new PT and UP need to created
			{	
			    while (available_pf < (used_pf + 2))   // create 2 avail pf
					evict_page();
					
			    create_page_table(working_addr.PD_index, cmd);
			    create_user_page(working_addr.PD_index, working_addr.PT_index, cmd);
			}   
		}
		if (d_flag == 1){dump_vmm();}	
		
	} while (strcmp (cmd, "EOF"));
	
	num_physical_frames = 1 + num_PT + num_UP;
	print_outputs();
	
}