void allocate_frame(int pid, int type, uint32 vpage)
{
	int i;
	for (i = 0; i < NFRAMES; i++)
	{
		if(invertpagetable[page_head].empty == TRUE)
		{
			invertpagetable[page_head].pid = pid;
			invertpagetable[page_head].type = type;
			invertpagetable[page_head].empty = FALSE;
			invertpagetable[page_head].vpage = vpage;
			return;
		}	
		page_head = (++page_head) % NFRAMES;		
	}
	kprintf ("Could not find any empty pages. Must evict\n");
	if (policy == FIFO)
	{
		kprintf("Eviction Policy: FIFO\n");
		uint32 evict_page = (page_head + 1) % NFRAMES;
		while(invertpagetable[page_head].type != FRAME_REG)
		{
			evict_page = (page_head + 1) % NFRAMES;
			if (evict_page == (page_head + 1) % NFRAMES)
			{
				kprintf ("All frames filled by directories or tables!\n");
			}
		}
		page_head = evict_page;
		
		int old_pid = invertpagetable[page_head].pid;
		int old_type = invertpagetable[page_head].type;
		int old_vpage = invertpagetable[page_head].vpage;

		int old_bs = bs_page(old_vpage);
		int old_pd = pd(old_vpage);
		int old_pt = pt(old_vpage);
		
		struct procent *old_prptr = &proctab[old_pid];
		pd_t *old_pd_t = old_prptr->prpagedir;
		pt_t *old_pt_t = (old_pd_t[old_pd].pd_base << 12);
		old_pt_t[old_pt].pt_pres = 0;
		char* addr = (char *)frame2addr(page_head);
		if(open_bs(old_prptr->prbs) == (uint32)-1 ||
		   write_bs(addr, old_prptr->prbs, old_bs)||
		   close_bs(old_prptr->prbs) == (uint32)-1)
		{
			kprintf("Backing store error during eviction!");
			return;
		}
		invertpagetable[page_head].pid = pid;
		invertpagetable[page_head].type = type;
		invertpagetable[page_head].empty = FALSE;
		invertpagetable[page_head].vpage = vpage;
	}

}
Esempio n. 2
0
/*------------------------------------------------------------------------
 *  kill  -  Kill a process and remove it from the system
 *------------------------------------------------------------------------
 */
syscall	kill(
	  pid32		pid		/* ID of process to kill	*/
	)
{
	intmask	mask;			/* Saved interrupt mask		*/
	struct	procent *prptr;		/* Ptr to process' table entry	*/
	int32	i;			/* Index into descriptors	*/

	mask = disable();
	if (isbadpid(pid) || (pid == NULLPROC)
	    || ((prptr = &proctab[pid])->prstate) == PR_FREE) {
		restore(mask);
		return SYSERR;
	}
    /*
     * Virtual memory-related cleanup section.
     */
    /* If backing store was allocated, close and deallocate it */
    int retries = 4;
    bsd_t bs = (bsd_t) -1;
    if(prptr->prbs == -1) {
        bs = 0;
    }
    while(bs == -1 && retries > 0) {
        bs = deallocate_bs(close_bs(prptr->prbs));
        retries --;
    }
    if(bs == -1) {
        kprintf("!!Warning: could not close and deallocate the backing store of pid %d. ",pid);
    }

    /* Deallocate all physical frames that the current process holds */
    free_proc_frames(pid);

    /* Free virtual memory free list */
    struct vmemblk *next, *cur = prptr->prvmemlist;
    while(cur!=NULL) {
        next = cur->mnext;
        freemem((char*)cur, sizeof(struct vmemblk));
        cur = next;
    }



	if (--prcount <= 1) {		/* Last user process completes	*/
		xdone();
	}

	send(prptr->prparent, pid);
	for (i=0; i<3; i++) {
		close(prptr->prdesc[i]);
	}
	freestk(prptr->prstkbase, prptr->prstklen);

	switch (prptr->prstate) {
	case PR_CURR:
		prptr->prstate = PR_FREE;	/* Suicide */
		resched();

	case PR_SLEEP:
	case PR_RECTIM:
		unsleep(pid);
		prptr->prstate = PR_FREE;
		break;

	case PR_WAIT:
		semtab[prptr->prsem].scount++;
		/* Fall through */

	case PR_READY:
		getitem(pid);		/* Remove from queue */
		/* Fall through */

	default:
		prptr->prstate = PR_FREE;
	}

	restore(mask);
	return OK;
}
Esempio n. 3
0
int free_frame(frame_t * frame)
{
	intmask mask;
	mask = disable();
	//LOG("Freeing");
	//print_frame(frame);
	if(frame->id <5)
	{
		LOG(" WHAT THE F**K %d %d", frame->id, frame->type);
		restore(mask);
		return OK;
	}
	//kprintf("id %d type %d ", frame->id, frame->type);
	//print_fifo_list();
	//kprintf("\n");
	if(frame == NULL)
	{
		restore(mask);
		return SYSERR;
	}
	else if(!FRAMEID_IS_VALID(frame->id))
	{
		restore(mask);
		return SYSERR;
	}
	else if(frame->type == FREE)
	{
		restore(mask);
		return OK;
	}
	else if(frame->type == PAGE){

		//print_fifo_list();
		//LOG("Got here 0.5");
		//3. Using the inverted page table, get vp, the virtual page number of the page to be replaced.
		uint32 vp = frame->vp_no;
		//4. Let a be vp*4096 (the first virtual address on page vp).

		hook_pswap_out(vp, frame->id + FRAME0);
		uint32 a = vp*PAGE_SIZE;

		virtual_addr * virt = (virtual_addr *) &a;

		//5. Let p be the high 10 bits of a. Let q be bits [21:12] of a.
		uint32 p = virt->page_directory_offset;
		uint32 q = virt->page_table_offset;

		//6. Let pid be the process id of the process owning vp.
		pid32 pid = frame->pid;


		//7. Let pd point to the page directory of process pid.
		struct	procent	*prptr;		/* Ptr to process table entry	*/
		prptr = &proctab[pid];
		pd_t * pd = prptr->pagedir;

		if( pd == NULL)
		{
			LOG(" pd doesn't exist ");
			restore(mask);
			return SYSERR;
		}
		bool8 pt_pres = FALSE;
		pt_pres = (bool8) pd[p].pd_pres;

		bool8 pg_pres = FALSE;
		bool8 dirty = FALSE;
		if(pt_pres)
		{	//8. Let pt point to the pid's p_th page table.
			pt_t * pt = (pt_t *) ((pd[p].pd_base) * PAGE_SIZE);
			pg_pres = (bool8) pt[q].pt_pres;
			uint32 pg_base = (uint32) pt[q].pt_base;
			if(pg_pres){
				if((uint32)FRAMEID_TO_VPAGE(frame->id) == pg_base)
				{
					pg_pres = TRUE;
					dirty  = pt[q].pt_dirty;
				}
				else
				{
					pg_pres = FALSE;
				}
			}




		}
		if(pg_pres)
		{
			frame_t * pt_frame = &frames[(pd[p].pd_base) - FRAME0];
			pt_t * pt = (pt_t *) ((pd[p].pd_base) * PAGE_SIZE);
			//9. Mark the appropriate entry of pt as not present.
			pt[q].pt_pres = 0;
			if(pt_frame->type == VPTBL){
				decr_frame_refcount(pt_frame);
				if(pt_frame->refcount == 0){
					pd[p].pd_pres = 0;
					free_frame(pt_frame);

				}


				bzero((char *)&pt[q], sizeof(pt_t));
			}
			else if(pt_frame->type == GPTBL)
			{
			//	kprintf(" Uh  OH");
			}
			// If the reference count has reached zero, you should mark the appropriate entry in pd as "not present."
			// This conserves frames by keeping only page tables which are necessary.
			//LOG("Got here 1.5");

			//If the dirty bit for page vp was set in its page table, you must do the following:
			//a)	Using the backing store map, find the store and page offset within the store, given pid and a.
			//		If the lookup fails, something is wrong. Print an error message and kill the process with id pid.
			//b)	Write the page back to the backing store.

			//LOG("Got here 2");

			if(dirty){
				bsd_t bs_store_id;
				int bs_store_page_offset;
				if(SYSERR == bs_map_check(pid, vp, &bs_store_id, &bs_store_page_offset))
				{
						kprintf("FATAL :Can't find the bs_map");
						restore(mask);
						kill(currpid);
						return SYSERR;
				}
				//print_frame(frame);
				if(BACKSTORE_ID_IS_VALID(frame->backstore) && BACKSTORE_OFFSET_IS_VALID(frame->backstore_offset) && frame->backstore == bs_store_id && frame->backstore_offset == bs_store_page_offset)
				{
					//LOG("Frame %d was dirty", frame->id);
					open_bs(frame->backstore);
					write_bs(FRAMEID_TO_PHYSICALADDR(frame->id), frame->backstore, frame->backstore_offset);
					close_bs(frame->backstore);
				}
				//else
				//{
				//	print_frame(frame);
				//	kprintf("Fatal error: Cannot locate backstore for vpage %d to swap out page for pid %d ", vp, pid);
				//	kill(pid);
				//	initialize_frame(frame);
				//	restore(mask);
				//	return SYSERR;
				//}
			}

			else{
				//print_frame(frame);
			}
		}



		//LOG("Got here 1");
		//10. If the page being removed belongs to the current process,
		// invalidate the TLB entry for the page vp, using the invlpg instruction (see Intel Manual, volumes II and III for more details on this instruction).
		// 11. In the inverted page table, decrement the reference count of the frame occupied by pt.


		//LOG(" Free frame");
		//print_frame(frame);
		enable_paging();
		initialize_frame(frame);
		// Update page table entries associated with this frame
		// set the frame to be free
	}
	else if(frame->type == VPTBL)
	{
		evict_from_fifo_list(frame);
		hook_ptable_delete(frame->id + FRAME0);
		enable_paging();
		initialize_frame(frame);
	}
	else if(frame->type == DIR)
	{
		struct procent * prptrNULL = &proctab[NULLPROC];
		pd_t * null_pg_dir = prptrNULL->pagedir;
		struct	procent	*prptr;		/* Ptr to process table entry	*/
		prptr = &proctab[currpid];
		if(prptr->pagedir!= null_pg_dir)
		{
			evict_from_fifo_list(frame);
			prptr->pagedir = prptrNULL->pagedir;
			switch_page_directory(prptr->pagedir);
			enable_paging();
			initialize_frame(frame);

		}
	}
	restore(mask);
	return OK;

}