//Swap out memory to the disk. The src_addr points to a page worth of user //memory. This will be read into the swap space. The disk_block pointer //will get set to the location at which the memory was stored. void swap_out (uint32_t *src_addr, block_sector_t *disk_block) { lock_acquire(&st->swap_table_lock); //Find available space on disk in the swap space block_sector_t block_offset = bitmap_scan_and_flip(st->map, 0, PGSIZE/BLOCK_SECTOR_SIZE, false); if (block_offset == BITMAP_ERROR) { lock_release(&st->swap_table_lock); PANIC ("BITMAP error in scanning swap space for block offset"); } //Update disk_block to the location on disk where the memory is being stored lock_release(&st->swap_table_lock); //write the memory from the src_addr onto the block int i = 0; for (i = 0; i<PGSIZE; i += BLOCK_SECTOR_SIZE) { block_write (st->swap_block, i/BLOCK_SECTOR_SIZE + block_offset, src_addr + i/sizeof(uint32_t)); } *disk_block = block_offset; }
/* Obtains and returns a group of PAGE_CNT contiguous free pages. If PAL_USER is set, the pages are obtained from the user pool, otherwise from the kernel pool. If PAL_ZERO is set in FLAGS, then the pages are filled with zeros. If too few pages are available, returns a null pointer, unless PAL_ASSERT is set in FLAGS, in which case the kernel panics. */ void * palloc_get_multiple (enum palloc_flags flags, size_t page_cnt) { struct pool *pool = flags & PAL_USER ? &user_pool : &kernel_pool; void *pages; size_t page_idx; if (page_cnt == 0) return NULL; lock_acquire (&pool->lock); page_idx = bitmap_scan_and_flip (pool->used_map, 0, page_cnt, false); lock_release (&pool->lock); if (page_idx != BITMAP_ERROR) pages = pool->base + PGSIZE * page_idx; else pages = NULL; if (pages != NULL) { if (flags & PAL_ZERO) memset (pages, 0, PGSIZE * page_cnt); } else { if (flags & PAL_ASSERT) PANIC ("palloc_get: out of pages"); } return pages; }
// returns the start sector of the swap slot where upage is written // all the vacant swap slots are set to FALSE size_t swap_write (void *kpage) { // ASSERT (kpage); // printf ("Swap write called for %p\n",upage); lock_acquire (&swap_table_lock); size_t idx = bitmap_scan_and_flip (swap_table, 0, SLOT_SIZE, false); if (idx == BITMAP_ERROR) { PANIC ("No more swap slot avaiable\n"); } struct disk *swap = disk_get (1,1); if (!swap) PANIC ("No swap disk found\n"); int offset; for (offset = 0; offset < SLOT_SIZE; offset++) { //disk_write (swap, idx + offset, upage + (offset * DISK_SECTOR_SIZE)); disk_write (swap, idx + offset, kpage + (offset * DISK_SECTOR_SIZE)); } lock_release (&swap_table_lock); return idx; }
struct cached_block* get_free_cache_buff(){ if(INODE_DEBUG) printf("get_free_cache_buff()\n"); int idx = bitmap_scan_and_flip(cache_bitmap, 0, 1, FREE); if(idx != BITMAP_ERROR){ struct cached_block* newblock = buffcache + idx; if(INODE_DEBUG) printf("get_free_cache_buff(): idx %d buffcache %x newblock %x buffcache+BUFF_CACHE_SIZE %x\n", idx, buffcache, newblock, buffcache+N_BUFFERS); memset(newblock, 0, sizeof(struct cached_block)); list_push_front(&buffcachelist, &newblock->elem); return newblock; } else{ struct cached_block* last_block = list_entry(list_back(&buffcache), struct cached_block, elem); cache_flush(NULL, last_block->sector); list_remove(&last_block->elem); traverse_buffcachelist(); list_push_front(&buffcachelist, &last_block->elem); memset(last_block->data, 0, BLOCK_SECTOR_SIZE); last_block->inode=NULL; last_block->sector=0; if(INODE_DEBUG) printf("get_free_cache_buff(): idx %d buffcache %x lastblock %x buffcache+BUFF_CACHE_SIZE %x\n", idx, buffcache, last_block, buffcache+N_BUFFERS); return last_block; } }
/* Allocates CNT consecutive sectors from the free map and stores the first into *SECTORP. Returns true if successful, false if not enough consecutive sectors were available or if the free_map file could not be written. */ bool free_map_allocate (size_t cnt, block_sector_t *sectorp) { block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); if (sector != BITMAP_ERROR) *sectorp = sector; return sector != BITMAP_ERROR; }
disk_sector_t swap_get_slot (void) { lock_acquire (&swap_bitmap_lock); disk_sector_t ret = bitmap_scan_and_flip (swap_slot, 0, SEC_PER_PG, false); lock_release (&swap_bitmap_lock); return ret; }
/* Allocate one frame in the swap block * Returns the swap_frame_number */ size_t swap_allocate_page ( struct swap_table * swap_table) { lock_acquire (&swap_table->lock_bitmap); size_t swap_frame_no = bitmap_scan_and_flip (swap_table->bitmap, 0, 1, false); lock_release(&swap_table->lock_bitmap); if (swap_frame_no == BITMAP_ERROR) PANIC ("out of swap space"); return swap_frame_no; }
uint32_t swap_out(void *frame) { uint32_t index = bitmap_scan_and_flip(swap_bitmap, 0, 1, 0); int i; for(i=0;i<SECTOR_PER_PAGE;i++) disk_write(swap_disk, (index * SECTOR_PER_PAGE) + i, frame + (i * DISK_SECTOR_SIZE)); return index; }
static size_t get_swap_slot (void) { lock_acquire (&swap_lock); size_t swap_idx = bitmap_scan_and_flip (used_map, 0, 1, false); lock_release (&swap_lock); if (swap_idx == BITMAP_ERROR) { PANIC ("SWAP PARTITION IS FULL"); } return swap_idx * SECTORS_PER_SWAP; }
void * allocator_alloc (struct allocator *a, size_t amount) { ASSERT (a != NULL); if (amount == 0) return NULL; size_t result = bitmap_scan_and_flip (a->used_map, 0, amount, false); if (result == BITMAP_ERROR) return NULL; return item_pos (a, result); }
/* Allocates a page-sized swap slot, returning the swapid of the allocated slot. Panics the kernel if no such free slot exists. */ swapid_t swap_alloc (void) { ASSERT (swap_block != NULL); lock_acquire (&swap_alloc_lock); size_t id = bitmap_scan_and_flip (free_blocks, 0, 1, true); if (id == BITMAP_ERROR) PANIC ("swap_alloc: out of swap space"); lock_release (&swap_alloc_lock); return id; }
/* Given a kernel page address (which corresponds to a frame) Swap a frame to swap disk and return the start index of it in swap table. If swap table is full, panic the kernel. */ size_t swap_to_disk (uint8_t *kpage) { if (!lock_held_by_current_thread (&swap_table_lock)) lock_acquire (&swap_table_lock); size_t index = bitmap_scan_and_flip (swap_table, 0, 1, false); if (index == BITMAP_ERROR) PANIC ("Swap table is full"); int i = 0; for (i = 0; i < 8; i++) block_write (swap_block, index * 8 + i, kpage + i * BLOCK_SECTOR_SIZE); lock_release (&swap_table_lock); return index; }
//switches from main memory to swap disk size_t swap_out (void *frame){ if (!swap_block || !swap_map) PANIC("Need swap partition but no swap partition present!"); //Goes into panic mode if there is no swap block or map basically the partition does not exist lock_acquire(&swap_lock); //Acquires the lock status size_t free_index = bitmap_scan_and_flip(swap_map, 0, 1, SWAP_FREE); if (free_index == BITMAP_ERROR) PANIC("Swap partition is full!"); //Goes into panic mode when there is a bitmap error for the particular index which basically means the partition is now full size_t i; for (i = 0; i < SECTORS_PER_PAGE; i++){ //Block writer block_write(swap_block, free_index * SECTORS_PER_PAGE + i, (uint8_t *) frame + i * BLOCK_SECTOR_SIZE); } lock_release(&swap_lock); //Releases swap lock status return free_index; //Returns the free index }
/* Allocates CNT consecutive sectors from the free map and stores the first into *SECTORP. Returns true if successful, false if not enough consecutive sectors were available or if the free_map file could not be written. */ bool free_map_allocate (size_t cnt, block_sector_t *sectorp) { block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); if (sector != BITMAP_ERROR && free_map_file != NULL && !bitmap_write (free_map, free_map_file)) { bitmap_set_multiple (free_map, sector, cnt, false); sector = BITMAP_ERROR; } if (sector != BITMAP_ERROR) *sectorp = sector; return sector != BITMAP_ERROR; }
/* move data from frame to swap slot */ size_t vm_swap_out(void *page){ lock_acquire(&swap_lock); size_t idx = bitmap_scan_and_flip(swap_partition, 0, 1, false); if (idx == BITMAP_ERROR){ /* No free slot */ lock_release(&swap_lock); PANIC("Swap partition is full\n"); } size_t i; for (i = 0; i < SECTORS_PER_PAGE ; i++) block_write(swap_slot, (idx * SECTORS_PER_PAGE) + i, page + (i * BLOCK_SECTOR_SIZE)); lock_release(&swap_lock); return idx; }
/* Swaps out page P, which must have a locked frame. */ bool swap_out(void *f) { if (!swap_device || !swap_bitmap) { PANIC("No swap partition available!"); } lock_acquire(&swap_lock); size_t free_index = bitmap_scan_and_flip(swap_bitmap, 0, 1, SWAP_FREE); lock_release(&swap_lock); if (free_index == BITMAP_ERROR) { PANIC("Swap partition is full!"); } size_t i; for (i = 0; i < SECTORS_PER_PAGE; i++) { block_write(swap_device, free_index * SECTORS_PER_PAGE + i, (uint8_t *) f + i * BLOCK_SECTOR_SIZE); } return free_index; }
/* Allocates CNT consecutive sectors from the free map and stores the first into *SECTORP. Returns true if successful, false if not enough consecutive sectors were available or if the free_map file could not be written. */ bool free_map_allocate (size_t cnt, block_sector_t *sectorp) { block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); if (sector != BITMAP_ERROR && free_map_file != NULL && !bitmap_write (free_map, free_map_file)) { bitmap_set_multiple (free_map, sector, cnt, false); sector = BITMAP_ERROR; } if (sector != BITMAP_ERROR){ *sectorp = sector; char zeroes[BLOCK_SECTOR_SIZE]; //Assignment 4 block_write(fs_device, sector,zeroes); //Assignment 4 } return sector != BITMAP_ERROR; }
uint32_t swap_write (const void *from) { uint32_t res, i; lock_acquire (&swap_lock); { size_t ind = bitmap_scan_and_flip (swap_bitmap, 0, 1, false); if (ind== BITMAP_ERROR) { PANIC ("no more swap space"); } res = ind; for (i = 0u; i < blocks_per_page; i++) { block_write (swap_block, ind * blocks_per_page + i, (const char *)from + i * BLOCK_SECTOR_SIZE); } } lock_release (&swap_lock); return res; }
size_t pick_slot_and_swap (void *page) { /* Finds the first slot which has value false (so it's free) and flips it, returning the index */ size_t index = bitmap_scan_and_flip (swap_slot_map, 0, 1, false); /* Write the ith BLOCK_SECTOR_SIZE bytes of the page to the block device. We have a mapping of SECTORS_PER_PAGE block sectors for every bit in the bitmap, so we can just multiply the index we got back by SECTORS_PER_PAGE to find the correct block sector to write to, and then increment this block sector index in each loop iteration */ int i = 0; for (; i < SECTORS_PER_PAGE; ++i) { block_write (block_device, (index * SECTORS_PER_PAGE) + i, page + (BLOCK_SECTOR_SIZE * i)); } return index; }
//Swap into memory from the disk. Swap_in must only be called if swap_out was //previously called, and disk_block must be the same disk_block from swap_out. //dest_addr should point to a page worth of memory to swap data into. void swap_in (uint32_t *dest_addr, block_sector_t *disk_block) { int i = 0; block_sector_t block_offset = *disk_block; //Read in a page worth of memory for(i = 0; i<PGSIZE; i += BLOCK_SECTOR_SIZE) { block_read (st->swap_block, i/BLOCK_SECTOR_SIZE + block_offset, dest_addr + i/sizeof(uint32_t)); } //Update the swap_table that this disk space is free again lock_acquire(&st->swap_table_lock); block_sector_t idx = bitmap_scan_and_flip(st->map, block_offset, PGSIZE/BLOCK_SECTOR_SIZE, true); //Assert that the page read in was previously marked as in use ASSERT(idx == block_offset); lock_release(&st->swap_table_lock); }
void add_page_to_swapfile(struct page_info* p) { lock_acquire(&swap_lock); // Find the first open 4KB slot in the swap file unsigned int index = bitmap_scan_and_flip(swapmap, 0, 1, false); ASSERT(index != BITMAP_ERROR); ASSERT(bitmap_test(swapmap, index)); // should be true i.e. occupied // Write out the passed-in page to that 4KB slot // We're going to need to write out eight sectors, one at a time block_sector_t sector_index = index * SECTORS_PER_PAGE; int i; for(i = 0; i < SECTORS_PER_PAGE; i++) { block_sector_t target_sector = sector_index + i; void* source_buf = (uint8_t *)p->virtual_address + (i * BLOCK_SECTOR_SIZE); block_write(swap_block, target_sector, source_buf); } p->swap_info.swap_index = index; lock_release(&swap_lock); }
/* Allocates CNT consecutive sectors from the free map and stores the first into *SECTORP. Returns true if successful, false if all sectors were available. */ bool free_map_allocate (size_t cnt, disk_sector_t *sectorp) { // lås id 6 lock_acquire(&free_map_lock); disk_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); if (sector != BITMAP_ERROR && free_map_file != NULL && !bitmap_write (free_map, free_map_file)) { bitmap_set_multiple (free_map, sector, cnt, false); sector = BITMAP_ERROR; } if (sector != BITMAP_ERROR) *sectorp = sector; lock_release(&free_map_lock); return sector != BITMAP_ERROR; }
static uint32_t _cache_find_ensured (struct block *block, block_sector_t sector) { lock_acquire (&cache_lock); int i; for (i = 0; i < CACHE_SIZE; ++i) { if (cache[i].block == block && cache[i].sector == sector) { lock_acquire (&cache[i].cs_lock); lock_release (&cache_lock); return i; } } uint32_t index = bitmap_scan_and_flip (used_slots, 0, 1, false); if (index == BITMAP_ERROR) index = _cache_evict (); _cache_fetch (index, block, sector); lock_acquire (&cache[index].cs_lock); lock_release (&cache_lock); return index; }
/** * function swaps the given page frame to the swap_disk_partition */ bool swap_page_out_to_disk_from_frame (struct supplementary_page_table_entry *page) { int i = 0; size_t open_index; ASSERT (page -> supplementary_frame_in_memory != NULL); ASSERT (lock_held_by_current_thread (&page -> supplementary_frame_in_memory ->this_lock)); if (swap_sectors_btmp == NULL) { PANIC("NO swap sectors bitmap available!!! :("); } // Get any free empty swap-sector index - to which we will write our page-frame data lock_acquire (&swap_lock); open_index = bitmap_scan_and_flip (swap_sectors_btmp, 0, 1, 0); lock_release (&swap_lock); if (open_index != BITMAP_ERROR) { page->area_swap = open_index; for (i = 0; i < NUM_OF_PER_PAGE_SECTORS; i++) { block_write (swap_partition, ( page->area_swap * NUM_OF_PER_PAGE_SECTORS ) + i, page->supplementary_frame_in_memory-> base_vir_address + i * BLOCK_SECTOR_SIZE); } // set that sector_bit_index in bitmap to 1 bitmap_set (swap_sectors_btmp, page->area_swap, true); page->sup_file = NULL; page->swap_write = false; page->rw_bytes = 0; page->file_offset = 0; return true; } return false; }
/* 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; }
size_t swap_out (void *frame) { if (!swap_block || !swap_map) { PANIC("Need swap partition but no swap partition present!"); } lock_acquire(&swap_lock); size_t free_index = bitmap_scan_and_flip(swap_map, 0, 1, SWAP_FREE); if (free_index == BITMAP_ERROR) { PANIC("Swap partition is full!"); } size_t i; for (i = 0; i < SECTORS_PER_PAGE; i++) { block_write(swap_block, free_index * SECTORS_PER_PAGE + i, (uint8_t *) frame + i * BLOCK_SECTOR_SIZE); } lock_release(&swap_lock); return free_index; }
/* * copy page in at kpg_vaddr to a slot, and return * slot's number. if no slot available, PANIC! */ uint32_t swap_store_pg(uint8_t* kpg_vaddr){ size_t slot_idx; ASSERT(swap_blk!=NULL); bool already_locked = lock_held_by_current_thread (&swap_lock); if (!already_locked) { lock_acquire(&swap_lock); } ASSERT(kpg_vaddr!=NULL); slot_idx = bitmap_scan_and_flip (swap_table, 0, 1, false); if (slot_idx != BITMAP_ERROR){ int i; for(i=0;i<8;i++){ block_write (swap_blk, slot_idx*8+i, kpg_vaddr+i*BLOCK_SECTOR_SIZE); } }else PANIC("No space for swap!"); if (!already_locked) { lock_release(&swap_lock); } return slot_idx; }
/* Gets a physical frame if available and maps it to a page obtained from the user pool */ void *get_frame(int flags) { //Check bitmap to see if free frame available struct thread *t = thread_current(); size_t idx = bitmap_scan_and_flip (fr_table->bm_frames, 0, 1, false); void * free_frame; //If available, fetch a page from user pool by calling palloc_get_page if(idx != BITMAP_ERROR) { free_frame = palloc_get_page(flags); if(!free_frame) { /* Evict frame - shouldn't happen here since we scan the bitmap first*/ } } else { //if fetch failed, PANIC for now. Implement evict later. PANIC("out of frames!"); } //else, set the appropriate bit in the ft bitmap (already done) //malloc free frame. map page to frame. Insert frame to hash table. struct frame_entry *frame = malloc(sizeof(struct frame_entry)); if(!frame) { PANIC("Malloc failed:Out of memory!"); } frame->frame = free_frame; frame->pagedir = t->pagedir; hash_insert (&fr_table->ft, &frame->hash_elem); //If bitset, frame used. Else, frame available return free_frame; //Return page address }
/* TODO need better comment swap out */ bool swap_out (struct frame_struct *pframe) { struct block *device = NULL; block_sector_t sector_no = 0; uint8_t *kpage = pframe->vaddr; if (kpage == NULL) { /* Virtual address invalid */ return false; } uint32_t pos = POS_MEM; uint32_t type = pframe->flag & TYPEBITS; uint32_t dirty = sup_pt_fs_is_dirty (pframe); uint32_t is_all_zero = pframe->flag & FS_ZERO; /* Zero and not dirty page need not swap out */ if (is_all_zero && !dirty) { pframe->flag = (pframe->flag & POSMASK) | POS_DISK; return true; } else { pframe->flag &= ~FS_ZERO; } if (type == TYPE_Stack) { device = sp_device; lock_acquire (&swap_set_lock); sector_no = bitmap_scan_and_flip (swap_free_map, 0, PGSIZE / BLOCK_SECTOR_SIZE, false); lock_release (&swap_set_lock); pos = POS_SWAP; goto write; } /* Write memory mapped file to disk */ if (type == TYPE_MMFile) { if (dirty) { device = fs_device; sector_no = pframe->sector_no; pos = POS_DISK; goto write; } else { sup_pt_set_swap_out (pframe, pframe->sector_no, true); lock_release (&pframe->frame_lock); return true; } } /* For executable, if dirty, write to swap space, otherwise do nothing. */ if (type == TYPE_Executable) { if (dirty) { device = sp_device; lock_acquire (&swap_set_lock); sector_no = bitmap_scan_and_flip (swap_free_map, 0, PGSIZE / BLOCK_SECTOR_SIZE, false); lock_release (&swap_set_lock); goto write; } else { sup_pt_set_swap_out (pframe, pframe->sector_no, true); lock_release (&pframe->frame_lock); return true; } } write: /* Write to disk or swap device */ if (device == fs_device) lock_acquire (&glb_lock_filesys); else lock_acquire (&glb_lock_swapsys); int i; for (i = 0; i < PGSIZE / BLOCK_SECTOR_SIZE; i++) { block_write (device, sector_no + i, kpage + BLOCK_SECTOR_SIZE * i); } if (device == fs_device) lock_release (&glb_lock_filesys); else lock_release (&glb_lock_swapsys); sup_pt_set_swap_out (pframe, sector_no, (pos == POS_DISK)); lock_release (&pframe->frame_lock); return true; }