/* Kontrollera alla adresser från och med start till och med den * adress som först innehåller ett noll-tecken, `\0'. (C-strängar * lagras på detta sätt.) */ bool verify_variable_length(char* buf) { /*if(pagedir_get_page(thread_current()->pagedir, (buf)) == NULL) return false;*/ int i=0; unsigned pg_last = pg_no(buf); while(true) { if(i==0 || pg_no(buf+i) != pg_last) { if(pagedir_get_page(thread_current()->pagedir, (buf+i)) == NULL) return false; if(is_end_of_string(buf+i)) break; } else if(pg_no(buf+i) == pg_last) { if(is_end_of_string(buf+i)) break; } pg_last = pg_no(buf+i); ++i; } return true; }
/* Frees the PAGE_CNT pages starting at PAGES. */ void palloc_free_multiple (void *pages, size_t page_cnt) { struct pool *pool; size_t page_idx; ASSERT (pg_ofs (pages) == 0); if (pages == NULL || page_cnt == 0) return; if (page_from_pool (&kernel_pool, pages)) pool = &kernel_pool; else if (page_from_pool (&user_pool, pages)) pool = &user_pool; else NOT_REACHED (); page_idx = pg_no (pages) - pg_no (pool->base); #ifndef NDEBUG memset (pages, 0xcc, PGSIZE * page_cnt); #endif ASSERT (bitmap_all (pool->used_map, page_idx, page_cnt)); bitmap_set_multiple (pool->used_map, page_idx, page_cnt, false); }
/* Returns true if PAGE was allocated from POOL, false otherwise. */ static bool page_from_pool (const struct pool *pool, void *page) { size_t page_no = pg_no (page); size_t start_page = pg_no (pool->base); size_t end_page = start_page + bitmap_size (pool->used_map); return page_no >= start_page && page_no < end_page; }
/* Fill a frametable_entry with data */ void frametable_entry_create(struct frametable_entry* fte, struct pagetable_entry* pte, tid_t tid, void *virt_address, bool pin) { fte->pte = pte; fte->tid = tid; fte->virt_address = pg_no(virt_address); fte->pin = pin; }
/* * Converts a pointer to any address into a number from * 0 to USER_PAGES-1 (the amount of pages in the userpool) * This can be used to as an index to access the frames * within the frame table. */ static uint32_t page_to_pagenum(void *page) { // pages are consecutive and nothing can be before the base ASSERT(page >= frametable.base_addr); // remove offset within frame page = pg_round_down(page); // address shift relative to base addr page -= (uintptr_t) frametable.base_addr; return pg_no(page); }
/* Kontrollera alla adresser från och med start till och inte med * (start+length). */ bool verify_fix_length(void* buf, int length) { /*if(buf == NULL) return false;*/ /*if(pagedir_get_page(thread_current()->pagedir,buf) == NULL) return false;*/ int i=0; if(pagedir_get_page(thread_current()->pagedir, (buf)) == NULL) return false; unsigned pg_last = pg_no(buf); for(i=0;i<length;++i) { if(pg_no(buf) != pg_last) { if(pagedir_get_page(thread_current()->pagedir, (buf)) == NULL) return false; } pg_last = pg_no(buf); buf = (char*)buf + 1; } return true; }
/* Obtains a single free page and returns its kernel virtual address. If PAL_USER is set, the page is obtained from the user pool, otherwise from the kernel pool. If PAL_ZERO is set in FLAGS, then the page is filled with zeros. If no pages are available, returns a null pointer, unless PAL_ASSERT is set in FLAGS, in which case the kernel panics. */ void * palloc_page (enum palloc_flags flags, void * upage, bool writable) { bool success = false; if(!(flags & PAL_USER)) PANIC ("This function cannot be called without PAL_USER flag set\n"); struct pool *pool = &frame_table.frame_pool; size_t page_idx; // empty page, and set to used lock_acquire (&pool->lock); page_idx = bitmap_scan_and_flip (pool->used_map, 0, 1, false); lock_release (&pool->lock); /* sets the members of cur_frame struct after is it allocated */ struct frame_entry * cur_frame; cur_frame = frame_table.frames + page_idx; cur_frame->pid = thread_current()->tid; cur_frame->page_num = pg_no(upage); cur_frame->reference = true; cur_frame->dirty = false; cur_frame->resident = true; success = install_page (upage, cur_frame->kpage, writable); if(DBG)printf("success after in mapping upage %p to kpage %p in palloc page = %d\n", upage, cur_frame->kpage, success); // execute flags if(!success) { if (flags & PAL_ASSERT) PANIC ("palloc_get: out of pages"); // change this? return NULL; } else if (flags & PAL_ZERO) memset (upage, 0, PGSIZE); return cur_frame->kpage; }
/* Validates all pointers between start and end in a few page table inspections as possible. Same notes as validate_byte(). */ static void validate_range(void *start, void *end) { int i; for(i = pg_no(end) - pg_no(start); i >= 0; i--) validate_byte(start + (PGSIZE * i)); }