struct frame_table_entry* frame_get_new_page (bool zero){ uint8_t *kpage; struct frame_table_entry *fte = NULL; redo: if(zero){ kpage = palloc_get_page (PAL_USER|PAL_ZERO); }else{ kpage = palloc_get_page (PAL_USER); } if(kpage!=NULL){ ASSERT (is_kernel_vaddr (kpage)); /* * TODO: * add new page into frame control here, * after all info be recorded, return the * page table entry. uaddr should be added * by latter... */ fte = malloc(sizeof(struct frame_table_entry)); fte->kpg_vaddr = kpage; fte->owner = thread_current(); fte->pinned = true; list_push_back (&frame_table, &fte->elem); // printf("thread %d released frame_lock\n",thread_current()->tid); return fte; }else{ //evict a page to swap(0) frame_evict_page(); goto redo; } }
/** * Allocate a new frame, * and return the address of the associated page. */ void* vm_frame_allocate (enum palloc_flags flags, void *upage) { lock_acquire (&frame_lock); void *frame_page = palloc_get_page (PAL_USER | flags); if (frame_page == NULL) { // page allocation failed. /* first, swap out the page */ struct frame_table_entry *f_evicted = pick_frame_to_evict( thread_current()->pagedir ); #if DEBUG printf("f_evicted: %x th=%x, pagedir = %x, up = %x, kp = %x, hash_size=%d\n", f_evicted, f_evicted->t, f_evicted->t->pagedir, f_evicted->upage, f_evicted->kpage, hash_size(&frame_map)); #endif ASSERT (f_evicted != NULL && f_evicted->t != NULL); // clear the page mapping, and replace it with swap ASSERT (f_evicted->t->pagedir != (void*)0xcccccccc); pagedir_clear_page(f_evicted->t->pagedir, f_evicted->upage); bool is_dirty = false; is_dirty = is_dirty || pagedir_is_dirty(f_evicted->t->pagedir, f_evicted->upage); is_dirty = is_dirty || pagedir_is_dirty(f_evicted->t->pagedir, f_evicted->kpage); swap_index_t swap_idx = vm_swap_out( f_evicted->kpage ); vm_supt_set_swap(f_evicted->t->supt, f_evicted->upage, swap_idx); vm_supt_set_dirty(f_evicted->t->supt, f_evicted->upage, is_dirty); vm_frame_do_free(f_evicted->kpage, true); // f_evicted is also invalidated frame_page = palloc_get_page (PAL_USER | flags); ASSERT (frame_page != NULL); // should success in this chance } struct frame_table_entry *frame = malloc(sizeof(struct frame_table_entry)); if(frame == NULL) { // frame allocation failed. a critical state or panic? lock_release (&frame_lock); return NULL; } frame->t = thread_current (); frame->upage = upage; frame->kpage = frame_page; frame->pinned = true; // can't be evicted yet // insert into hash table hash_insert (&frame_map, &frame->helem); list_push_back (&frame_list, &frame->lelem); lock_release (&frame_lock); return frame_page; }
/* Allocate frame */ void *vm_alloc_frame(enum palloc_flags flag, struct supp_page_entry *s){ if ((flag & PAL_USER) == 0) return NULL; void *page = palloc_get_page(flag); if (!page){ /* No more free space */ struct vm_frame *f = vm_evict_frame(s); page = palloc_get_page(flag); f->page = page; } else vm_add_frame(page, s); return page; }
void *frame_alloc(enum palloc_flags flag, struct page *pg){ if(flag<4 ) //user 영역이 아님 return NULL; void *frame = palloc_get_page(flag); if( frame) { frame_add_to_table(frame, pg); } else { while(!frame) { frame=frame_victim(flag); lock_release(&frame_table_lock); } frame_add_to_table(frame, pg); } return frame; }
void *fm_allocate (enum palloc_flags flags, bool lock) { lock_acquire(&frame_table_lock); void *kaddr = palloc_get_page(PAL_USER | flags); struct frame *fm; if (kaddr == NULL){ fm = select_fm(); fm->isPinned = true; fm->locked = lock; kaddr = fm->k_addr; struct hash *ht_thread_uaddr = &fm->ht_thread_uaddr; hash_first(&fm->iter_htu, ht_thread_uaddr); struct thread_uaddr *thread_uaddr; while (hash_next(&fm->iter_htu)){ thread_uaddr = hash_entry(hash_cur(&fm->iter_htu), struct thread_uaddr, elem); struct page* p = find_page(thread_uaddr->uaddr, thread_uaddr->t); p->isLoaded = false; pagedir_clear_page(thread_uaddr->t->pagedir, p->vaddr); if (p->type == STACK){ page_to_swap(p); } else if (p->type == SEGMENT){ if (p->writable && (if_fm_dirty(fm) || p->isDirty)){ p->isDirty = true; page_to_swap(p); } } else { write_mmap_page_to_file(p); } } hash_clear(&fm->ht_thread_uaddr, remove_thread_uaddr); } else {
/* Returns the address of the page table entry for virtual address VADDR in page directory PD. If PD does not have a page table for VADDR, behavior depends on CREATE. If CREATE is true, then a new page table is created and a pointer into it is returned. Otherwise, a null pointer is returned. */ uint32_t * lookup_page (uint32_t *pd, const void *vaddr, bool create) { uint32_t *pt, *pde; ASSERT (pd != NULL); /* Shouldn't create new kernel virtual mappings. */ ASSERT (!create || is_user_vaddr (vaddr)); /* Check for a page table for VADDR. If one is missing, create one if requested. */ pde = pd + pd_no (vaddr); if (*pde == 0) { if (create) { pt = palloc_get_page (PAL_ZERO); if (pt == NULL) return NULL; *pde = pde_create (pt); } else return NULL; } /* Return the page table entry. */ pt = pde_get_pt (*pde); return &pt[pt_no (vaddr)]; }
void* frame_victim (enum palloc_flags flag) { lock_acquire(&frame_table_lock); struct list_elem *e= list_begin(&frame_table); //list_ victim_frame=list_pop_front(&frame_table); if(victim_frame ==NULL) { } else { victim_frame->page->valid=false; pagedir_clear_page(victim_frame->thread->pagedir, victim_frame->page->vaddr); palloc_free_page(victim_frame->frame); return palloc_get_page(flag); } lock_release(&frame_table_lock); }
/*! Obtain a frame, either through palloc() or through eviction */ struct frame_table_entry *obtain_frame(enum palloc_flags flag, struct supp_table *pte) { void *page; struct frame_table_entry *newframe; page = palloc_get_page(flag); if (!page) page = frame_evict(flag); if (!page) PANIC("run out of frames!\n"); /*! Allocate a frame table entry and initialize it */ newframe = (struct frame_table_entry *)\ malloc(sizeof(struct frame_table_entry)); if (!newframe) PANIC("malloc failure\n"); newframe->physical_addr = page; newframe->owner = thread_current(); newframe->spt = pte; if (f_table.lock.holder != thread_current()) lock_acquire(&f_table.lock); list_push_back(&f_table.table, &newframe->elem); lock_release(&f_table.lock); return newframe; }
/* 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; }
/* Allocates an unused user frame. If there */ struct frame *frame_alloc() { struct frame *f = NULL; lock_acquire(&ft_lock); void *pg = palloc_get_page(PAL_USER); if(pg == NULL) { /* If there are no frames left, evict a page. */ f = get_frame_for_eviction(); lock_release(&ft_lock); lock_acquire(&f->page->moving);//TODO this should never block. need to use a monitor instead to synch between the evictor and call to page_free() evict(f); } else { /* Initialize new frame. */ f = malloc(sizeof(struct frame)); f->addr = pg; lock_init(&f->evicting); lock_acquire(&f->evicting); /* Add frame to frame table. */ hash_insert(&frame_table, &f->elem); lock_release(&ft_lock); } return f; }
/*! Use the clock algorithm to select a frame to evict and execute the eviction. */ void * frame_evict(enum palloc_flags flag) { struct list_elem *ce; struct thread *ct; struct frame_table_entry *cf; int i; if (f_table.lock.holder != thread_current()) lock_acquire(&f_table.lock); /* Get frame table lock */ if (list_empty(&f_table.table)) { lock_release(&f_table.lock); /* Nothing to evict */ return NULL; } f_table.hand = f_table.hand % list_size(&f_table.table); ce = list_begin(&f_table.table); /* Begin iteration */ for (i = 0; i < f_table.hand; i++) { /* Find where the "hand" points to: that is where the iteration starts */ ce = list_next(ce); } while (true) { cf = list_entry(ce, struct frame_table_entry, elem); ct = cf->owner; if (!cf->spt->pinned) { /* If pinned, skip this frame */ if (pagedir_is_accessed(ct->pagedir, cf->spt->upage)) /* If accessed, clear accessed bit */ pagedir_set_accessed(ct->pagedir, cf->spt->upage, false); else { /* Swap out the page! */ if (cf->spt->type != SPT_MMAP) { cf->spt->fr = NULL; cf->spt->type = SPT_SWAP; cf->spt->swap_index = swap_out(cf->physical_addr); } /* Write the frame back to the map'd file */ else if (cf->spt->type == SPT_MMAP && pagedir_is_dirty(ct->pagedir, cf->spt->upage)) { cf->spt->fr = NULL; file_write_at(cf->spt->file, cf->physical_addr, cf->spt->read_bytes, cf->spt->ofs); } /* Clear the frame */ list_remove(ce); pagedir_clear_page(ct->pagedir, cf->spt->upage); palloc_free_page(cf->physical_addr); free(cf); lock_release(&f_table.lock); return palloc_get_page(flag); } } ce = list_next(ce); ++f_table.hand; if (ce == list_end(&f_table.table)) { /* Iterate circularly */ ce = list_begin(&f_table.table); f_table.hand = 0; } } }
/* Allocates and returns a page. First tries palloc, if fails, evicts a frame and returns the newly available frame */ void * frame_get_page (enum palloc_flags flags) { lock_acquire (&frame_lock); void *kpage = palloc_get_page (flags); if (kpage == NULL) kpage = swap_evict (); lock_release (&frame_lock); return kpage; }
/* 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) { void *temp; temp=palloc_get_page(PAL_USER); if(temp!=NULL) { struct frame *f=malloc(sizeof(struct frame)); lock_init(&f->lock); f->page=page; f->base=temp; lock_acquire(&framelock); list_push_front(&frametable,&f->elem); lock_release(&framelock); return f; } struct list_elem *e1; e1=list_begin(&frametable); while(1) { lock_acquire(&framelock); struct frame *fr; fr=malloc(sizeof(struct frame)); /*fr=list_entry(e1,struct frame,elem);*/ /* bool temp=pagedir_is_accessed((fr->page->thread)->pagedir,fr->page->addr); if(temp) { pagedir_set_accessed((fr->page->thread)->pagedir,fr->page->addr,false);*/ e1=list_next(e1); if(e1==list_end(&frametable)) { e1=list_begin(&frametable); } continue; } struct frame *fr; if(fr->page->iswrite) {/* fr->page->mode=swap_out(*/ } else { } fr->page=page; lock_release(&framelock); return fr; }
/* Initializes the kernel TSS. */ void tss_init (void) { /* Our TSS is never used in a call gate or task gate, so only a few fields of it are ever referenced, and those are the only ones we initialize. */ tss = palloc_get_page (PAL_ASSERT | PAL_ZERO); tss->ss0 = SEL_KDSEG; tss->bitmap = 0xdfff; tss_update (); }
bool from_file (struct spage_entry *se) { struct thread *t = thread_current (); struct file *file = se->myfile; off_t ofs = se->ofs; uint8_t upage = se->upage; uint32_t read_bytes = se->read_bytes; uint32_t zero_bytes = se->zero_bytes; bool writable = se->writable; ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0); ASSERT (pg_ofs (upage) == 0); ASSERT (ofs % PGSIZE == 0); // lock_acquire (&filesys_lock); file_seek (file, ofs); // lock_release (&filesys_lock); if ( !(read_bytes > 0 || zero_bytes > 0) ) return false; /* Calculate how to fill this page. We will read PAGE_READ_BYTES bytes from FILE and zero the final PAGE_ZERO_BYTES bytes. */ size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; size_t page_zero_bytes = PGSIZE - page_read_bytes; /* Get a page of memory. */ uint8_t *kpage = palloc_get_page (PAL_USER); if (kpage == NULL) return false; /* Load this page. */ // lock_acquire (&filesys_lock); if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) { // lock_release (&filesys_lock); palloc_free_page (kpage); return false; } // lock_release (&filesys_lock); memset (kpage + page_read_bytes, 0, page_zero_bytes); /* Add the page to the process's address space. */ if (!install_page (upage, kpage, writable)) { palloc_free_page (kpage); return false; } return true; }
/* Creates a new kernel thread named NAME with the given initial PRIORITY, which executes FUNCTION passing AUX as the argument, and adds it to the ready queue. Returns the thread identifier for the new thread, or TID_ERROR if creation fails. If thread_start() has been called, then the new thread may be scheduled before thread_create() returns. It could even exit before thread_create() returns. Contrariwise, the original thread may run for any amount of time before the new thread is scheduled. Use a semaphore or some other form of synchronization if you need to ensure ordering. The code provided sets the new thread's `priority' member to PRIORITY, but no actual priority scheduling is implemented. Priority scheduling is the goal of Problem 1-3. */ tid_t thread_create (const char *name, int priority, thread_func *function, void *aux) { struct thread *t; struct kernel_thread_frame *kf; struct switch_entry_frame *ef; struct switch_threads_frame *sf; tid_t tid; enum intr_level old_level; ASSERT (function != NULL); /* Allocate thread. */ t = palloc_get_page (PAL_ZERO); if (t == NULL) return TID_ERROR; /* Initialize thread. */ init_thread (t, name, priority); tid = t->tid = allocate_tid (); /* Prepare thread for first run by initializing its stack. Do this atomically so intermediate values for the 'stack' member cannot be observed. */ old_level = intr_disable (); /* Stack frame for kernel_thread(). */ kf = alloc_frame (t, sizeof *kf); kf->eip = NULL; kf->function = function; kf->aux = aux; /* Stack frame for switch_entry(). */ ef = alloc_frame (t, sizeof *ef); ef->eip = (void (*) (void)) kernel_thread; /* Stack frame for switch_threads(). */ sf = alloc_frame (t, sizeof *sf); sf->eip = switch_entry; sf->ebp = 0; intr_set_level (old_level); /* Add to run queue. */ thread_unblock (t); //we need to call thread yield now to check if this thread //has the highest priority thread_yield(); return tid; }
void page_replacement(void *vaddr) { uint32_t *paddr,*lru_page; if ((paddr = palloc_get_page(PAL_USER)) != NULL) swap_in(vaddr, paddr); else { lru_page = lru_get_page(); swap_out(lru_page); swap_in(vaddr,lru_page); } }
/* Create a minimal stack by mapping a zeroed page at the top of user virtual memory. */ static bool setup_stack (void **esp) { uint8_t *kpage; bool success = false; kpage = palloc_get_page (PAL_USER | PAL_ZERO); if (kpage != NULL) { success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true); if (success) *esp = PHYS_BASE; else palloc_free_page (kpage); } return success; }
void stack_growth(void *vaddr){ uint32_t *paddr,*lru_page; if ((paddr = palloc_get_page(PAL_ZERO)) != NULL) { fte_create(paddr, false); install_page_ext (pg_round_down(vaddr), paddr, true); set_page_valid(pg_round_down(vaddr), paddr); } else { lru_page = lru_get_page(); swap_out(lru_page); set_page_valid(pg_round_down(vaddr), lru_page); } }
struct page *alloc_page (enum palloc_flags flags) { struct page *page; void *kaddr = palloc_get_page(flags); while (kaddr == NULL) { kaddr = try_to_free_pages(flags); } page = (struct page*)malloc(sizeof(struct page)); page->kaddr = kaddr; page->thread = thread_current(); add_page_to_lru_list(page); return page; }
/* Loads a segment starting at offset OFS in FILE at address UPAGE. In total, READ_BYTES + ZERO_BYTES bytes of virtual memory are initialized, as follows: - READ_BYTES bytes at UPAGE must be read from FILE starting at offset OFS. - ZERO_BYTES bytes at UPAGE + READ_BYTES must be zeroed. The pages initialized by this function must be writable by the user process if WRITABLE is true, read-only otherwise. Return true if successful, false if a memory allocation error or disk read error occurs. */ static bool load_segment (struct file *file, off_t ofs, uint8_t *upage, uint32_t read_bytes, uint32_t zero_bytes, bool writable) { ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0); ASSERT (pg_ofs (upage) == 0); ASSERT (ofs % PGSIZE == 0); file_seek (file, ofs); while (read_bytes > 0 || zero_bytes > 0) { /* Calculate how to fill this page. We will read PAGE_READ_BYTES bytes from FILE and zero the final PAGE_ZERO_BYTES bytes. */ size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; size_t page_zero_bytes = PGSIZE - page_read_bytes; /* Get a page of memory. */ uint8_t *kpage = palloc_get_page (PAL_USER); if (kpage == NULL) return false; /* Load this page. */ if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) { palloc_free_page (kpage); return false; } memset (kpage + page_read_bytes, 0, page_zero_bytes); /* Add the page to the process's address space. */ if (!install_page (upage, kpage, writable)) { palloc_free_page (kpage); return false; } /* Advance. */ read_bytes -= page_read_bytes; zero_bytes -= page_zero_bytes; upage += PGSIZE; } return true; }
/* Initialize the frame manager. */ void frame_init (void) { void *base; lock_init (&scan_lock); frames = malloc (sizeof *frames * init_ram_pages); if (frames == NULL) PANIC ("out of memory allocating page frames"); while ((base = palloc_get_page (PAL_USER)) != NULL) { struct frame *f = &frames[frame_cnt++]; lock_init (&f->lock); f->base = base; f->page = NULL; } }
void * frame_evict (enum palloc_flags flags) { lock_acquire (&frame_table_lock); struct list_elem *e = list_begin (&frame_table); while (true) { struct frame_entry *frame_entry = list_entry (e, struct frame_entry, elem); struct SP_entry *page_entry = frame_entry->page_entry; if (!page_entry->pinned) { struct thread *t = frame_entry->thread; if (pagedir_is_accessed (t->pagedir, page_entry->page)) { pagedir_set_accessed (t->pagedir, page_entry->page, false); } else { if (pagedir_is_dirty (t->pagedir, page_entry->page) || page_entry->type == SP_SWAP) { if (page_entry->type == SP_MMAP) { lock_acquire (&filesys_lock); file_write_at (page_entry->file, frame_entry->frame, page_entry->read_bytes, page_entry->offset); lock_release (&filesys_lock); } else { page_entry->type = SP_SWAP; page_entry->swap_index = swap_out (frame_entry->frame); } } page_entry->is_loaded = false; list_remove (&frame_entry->elem); pagedir_clear_page (t->pagedir, page_entry->page); palloc_free_page (frame_entry->frame); free (frame_entry); lock_release (&frame_table_lock); return palloc_get_page (flags); } } e = list_next (e); if (e == list_end (&frame_table)) { e = list_begin (&frame_table); } } }
/* Given a virtual address (page) find a frame to put the page in and return the physical address of the frame */ void* frame_obtain (enum palloc_flags flags, void* uaddr) { struct frame_table_entry* fte; /* Try and obtain frame in user memory */ void *kaddr = palloc_get_page (flags); /* Successfully obtained frame */ if (kaddr != NULL) { /* Create new frame table entry mapping the given page to the allocated frame */ fte = (struct frame_table_entry *) malloc (sizeof (struct frame_table_entry)); fte->owner = thread_current (); fte->kaddr = kaddr; fte->uaddr = pg_round_down (uaddr); lock_acquire (&frame_table_lock); list_push_front (&frame_table, &fte->elem); lock_release (&frame_table_lock); return fte->kaddr; } /* Failed to obtain frame */ else { /* Perform eviction to release a frame and try allocation again */ if (PAGE_EVICTION) { return frame_evict (uaddr); } else { PANIC ("Failed to allocate frame - eviction disabled."); } } }
void * frame_alloc (enum palloc_flags flags, struct SP_entry *page_entry) { if ((flags & PAL_USER) == 0) { return NULL; } void *frame = palloc_get_page (flags); if (frame) { frame_add (frame, page_entry); } else { while (!frame) { frame = frame_evict (flags); } if (!frame) { PANIC ("Frame evict failed. Swap is full!"); } frame_add (frame, page_entry); } return frame; }
void * swap (void) { struct frame_entry *victim_frame = find_victim(); struct spage_entry *victim_spage_entry = victim_frame->spe; uint32_t sectornum = swap_out(victim_frame->frame); pagedir_clear_page(victim_frame->t->pagedir,victim_spage_entry->uaddr); victim_spage_entry->indisk = true; victim_spage_entry->sec_no = sectornum; palloc_free_page(victim_frame->frame); falloc_free_frame(victim_frame->frame); void *kpage = palloc_get_page(PAL_USER|PAL_ZERO); ASSERT(kpage != NULL); return kpage; }
int sys_open(const char* file) { // memory validation check_user((const uint8_t*) file); struct file* file_opened; struct file_desc* fd = palloc_get_page(0); if (!fd) { return -1; } lock_acquire (&filesys_lock); file_opened = filesys_open(file); if (!file_opened) { palloc_free_page (fd); lock_release (&filesys_lock); return -1; } fd->file = file_opened; //file save // directory handling struct inode *inode = file_get_inode(fd->file); if(inode != NULL && inode_is_directory(inode)) { fd->dir = dir_open( inode_reopen(inode) ); } else fd->dir = NULL; struct list* fd_list = &thread_current()->file_descriptors; if (list_empty(fd_list)) { // 0, 1, 2 are reserved for stdin, stdout, stderr fd->id = 3; } else { fd->id = (list_entry(list_back(fd_list), struct file_desc, elem)->id) + 1; } list_push_back(fd_list, &(fd->elem)); lock_release (&filesys_lock); return fd->id; }
/* Creates a copy of user string US in kernel memory and returns it as a page that must be freed with palloc_free_page(). Truncates the string at PGSIZE bytes in size. Call thread_exit() if any of the user accesses are invalid. */ static char * copy_in_string (const char *us) { char *ks; char *upage; size_t length; ks = palloc_get_page (0); if (ks == NULL) thread_exit (); length = 0; for (;;) { upage = pg_round_down (us); if (!page_lock (upage, false)) goto lock_error; for (; us < upage + PGSIZE; us++) { ks[length++] = *us; if (*us == '\0') { page_unlock (upage); return ks; } else if (length >= PGSIZE) goto too_long_error; } page_unlock (upage); } too_long_error: page_unlock (upage); lock_error: palloc_free_page (ks); thread_exit (); }
void* frame_get_page(enum palloc_flags flags, void *uaddr) { /* Ensure we are always getting from the user pool */ flags = PAL_USER | flags; /* Attempt to allocate a page, if this comes back null then we need to evict */ void *page = palloc_get_page(flags); /* TODO: not sure if this is right way to check that we ran out of pages Maybe we should check if pages within some count?? */ if(page != NULL) { struct frame *frm = (struct frame*) malloc(sizeof(struct frame)); frm->physical_address = page; frm->user_address = uaddr; frm->owner = thread_current (); list_push_front(&frame_list, &frm->elem); } else { printf("WE RAN OUT OF SPACE. SHIT!\n"); } }
/* initializes the cashing system */ void cache_init () { /* loop variables */ int i,j; /* allocate kernel pages for cache */ for (i = 0; i < (CACHE_SIZE / blocks_per_page); i++) { /* get a page from kernel memory */ void *kpage = palloc_get_page (PAL_ZERO); for (j = 0; j < blocks_per_page; j++) { /* init the block */ struct cache_block *c = (struct cache_block*) malloc(sizeof(struct cache_block)); c->reader = 0; c->writer = 0; c->bid = -1; c->kpage = kpage + j * BLOCK_SECTOR_SIZE ; c->dirty = false; c->accessed = false; /* save to cache */ cache[i * blocks_per_page + j] = c; } } /*create a bitmap that represents the free entries in the cache table */ cache_table = bitmap_create (CACHE_SIZE); /* init list, lock and counting semaphore */ lock_init(&cache_globallock); list_init(&readahead_list); sema_init(&readahead_cnt, 0); }