You are on page 1of 5

#include

#include
#include
#include
#include
#include

<types.h>
<kern/errno.h>
<lib.h>
<thread.h>
<addrspace.h>
<vm.h>

struct frame_table_entry {
int free;
int locked;
};
/*
top_of_ram
_______________________
frametable
_______________________
int free_head
_______________________
int free_queue[nframes]
_______________________

*/
/* Place your frametable data-structures here
* You probably also want to write a frametable initialisation
* function and call it from vm_bootstrap
*/
static struct spinlock stealmem_lock = SPINLOCK_INITIALIZER;
static struct spinlock frametable_lock = SPINLOCK_INITIALIZER;
static int nframes;
int *queue = 0;
struct frame_table_entry *frametable = 0;
int *free_frame_head;

void frametable_init( void );


void frametable_init( void ) {
r
paddr_t location;
paddr_t top_of_ram = ram_getsize();
nframes = top_of_ram/PAGE_SIZE;

//find highest free position in ram


location = top_of_ram - ( (nframes) * sizeof( struct frame_table_entry ) );
//convert into a kaddr
location = PADDR_TO_KVADDR(location);
//associate pointer to this location
frametable = (struct frame_table_entry *) location;
int i;
//set all entries as free
for( i=0; i < nframes ; i++ ){
frametable[i].free = 1;
frametable[i].locked = 0;
}
//create free frame queue
queue = (int *)(location - ((nframes) * sizeof( int )));
//mark kernel filled spots as occupied
//get location/(size from 0) of first free space after kernel space
int free_base = ram_getfirstfree();
//get no. of pages occupied
free_base = free_base/PAGE_SIZE;
//set pages in our table to not-free
for( i=0; i<free_base+1; i++ ){
frametable[i].free = 0;
frametable[i].locked = 1;
}
//mark table spots as occupied
//find memory taken by table (N*entry size)
int tablepages = ((nframes) * sizeof( struct frame_table_entry )) + ((nframes)
* sizeof( int ));
//find no. pages occupied by table
tablepages = (tablepages/PAGE_SIZE);
//set pages in our table to not-free
for( i=0; i<tablepages+1; i++ ){
frametable[nframes - i - 1].free = 0;
frametable[nframes - i - 1].locked = 1;
}

//init free frame queue


for( i = tablepages+free_base; i<nframes; i++ ){
queue[i] = i+tablepages;

}
//we will never fill the free queue as frame table will be taking up frames
//thus we have the queue head stored in the lowest queue location
//queue is fifo, and grows downwards from the bottom of the frametable
//frametable
//_________________
//queue
//|
//| grows downwards
//V
queue[0] = tablepages+free_base;
return;
}

/* Note that this function returns a VIRTUAL address, not a physical


* address
* WARNING: this function gets called very early, before
* vm_bootstrap(). You may wish to modify main.c to call your
* frame table initialisation function, or check to see if the
* frame table has been initialised and call ram_stealmem() otherwise.
*/
vaddr_t alloc_kpages(unsigned int npages)
{
paddr_t addr;
//frametable not initialised, steal-ram temporarily
if( frametable == 0 ){
spinlock_acquire(&stealmem_lock);
addr = ram_stealmem(npages);
spinlock_release(&stealmem_lock);
if(addr == 0)
return 0;
return PADDR_TO_KVADDR(addr);
}
//frametable is initialised, therefore we can manage.
else{
//get frametable spinlock
spinlock_acquire(&frametable_lock);
int i=0;

//retrieve free frame for queue

i = queue[queue[0]];
//increment head
queue[0]++;
//convert index to paddr
addr = i*PAGE_SIZE;
//convert into kaddr
addr = PADDR_TO_KVADDR(addr);
//verify frame is valid
if( addr > (paddr_t)&frametable[(nframes - 1)] ){
panic( "Out of ram/Invalid addr obtained" );
}
//assign page as occupied
frametable[i].free = 0;
//zero out frame
int *blockhead = (int *)addr;
int noints = PAGE_SIZE/sizeof(int);
for( i=0; i<noints; i++ ){
blockhead[i] = 0;
}
//release lock
spinlock_release(&frametable_lock);
//return kernel address
return addr;
}

}
// free previously allocated pages
void free_kpages(vaddr_t addr)
{
(void) addr;
if( frametable == 0 ){
(void) addr;
}
else{
//get frametable spinlock
spinlock_acquire(&frametable_lock);
//get table index from address
int i = KVADDR_TO_PADDR( addr ) / PAGE_SIZE;
if( frametable[i].locked != 1 ){
//mark frame as free on table
frametable[i].free = 1;

queue[0]--;
queue[queue[0]] = i;
}
else{
panic(" tried to free reserved frame");
}
//release frametable spinlock
spinlock_release(&frametable_lock);
}
}

You might also like