Example #1
0
File: pager.c Project: gapry/aos-1
/*
 * Unmaps all the page table entries and pages and frees the frames for a tid
 */
void unmap_process(L4_ThreadId_t tid_killed) {
  //Clear page table
  for(int i=0;i<numPTE;i++) {
    if(L4_ThreadNo(page_table[i].tid) == L4_ThreadNo(tid_killed)) {
	L4_UnmapFpage(page_table[i].tid,page_table[i].pageNo);      
	frame_free(new_low + i * PAGESIZE);
        page_table[i].tid = L4_nilthread;
	page_table[i].referenced = 0;
	page_table[i].dirty = 0;
	page_table[i].being_updated = 0;
	page_table[i].error_in_transfer = 0;
        page_table[i].pinned = 0;
    }
  }
  
  //Clear swap table
  for(int i=0;i<MAX_SWAP_ENTRIES;i++) {
    if(L4_ThreadNo(swap_table[i].tid) == L4_ThreadNo(tid_killed)) {
        swap_table[i].tid = L4_nilthread;
	swap_table[i].next_free = head_free_swap;
	head_free_swap = i;
    }
  }
  //Remove later not required
  L4_CacheFlushAll();
}
Example #2
0
File: pager.c Project: gapry/aos-1
/*
 * Returns the page table index to be evicted and the static variable 
 * ensures it remembers the last search index for the next eviction
 * Uses the second chance page replacement algorithm
 */
static int evictPage(void) {
  static int evictIndex = 0;
  int copyIndex = evictIndex;
  int counter = 0;
  while(1) {
    counter++;
    //Check that a being updated and pinned entry is not evicted
    if((L4_ThreadNo(page_table[evictIndex].tid) == L4_ThreadNo(L4_nilthread)) || (page_table[evictIndex].referenced == 0 && page_table[evictIndex].being_updated == 0 && page_table[evictIndex].pinned == 0))
      return evictIndex;
    else if(page_table[evictIndex].being_updated == 0 && page_table[evictIndex].pinned == 0){
      page_table[evictIndex].referenced = 0;
      L4_UnmapFpage(page_table[evictIndex].tid,page_table[evictIndex].pageNo);
    } else if (page_table[evictIndex].being_updated == 1) {
      copyIndex = (copyIndex + 1) % numPTE;
    }
    //Check if we have done one full cycle of page table search without an eviction owing to 
    //updation then bail else we go into an infinite loop
    if(counter == numPTE) {
      if(copyIndex == evictIndex) {
	return -1;
      }
      numPTE = 0;
      copyIndex = evictIndex;
    }
    evictIndex = (evictIndex + 1) % numPTE;
  }
}
Example #3
0
File: swapper.c Project: gz/aos10
/**
 * Dereferences a page. This just unmaps it in the L4 page table.
 * @param page
 */
static void dereference(page_queue_item* page) {

	if(L4_UnmapFpage(page->tid, L4_FpageLog2(page->virtual_address, PAGESIZE_LOG2)) == FALSE) {
		dprintf(0, "Can't unmap page at 0x%X (error:%d)\n", page->virtual_address, L4_ErrorCode());
	}

	//L4_CacheFlushRange(page->tid, pager_table_lookup(page->tid, page->virtual_address)->address, pager_table_lookup(page->tid, page->virtual_address)->address+PAGESIZE);
}
Example #4
0
File: pager.c Project: gapry/aos-1
/*
 * Function to unmap all entries from the page table(used for milestone 2)
 */
void
unmap_all()
{
    for (int i = 0; i < numPTE; i++)
    {
        if (L4_ThreadNo(page_table[i].tid) != L4_ThreadNo(L4_nilthread))
        {
            L4_Fpage_t toUnmap = page_table[i].pageNo;
            L4_UnmapFpage(page_table[i].tid, toUnmap);
        }
    }
}
Example #5
0
File: pager.c Project: gapry/aos-1
/*
 * This function loads the entire elf file into the phsical frames and
 * maps fpages corresponding to virtual address in elf file to the process
 */
int load_code_segment_virtual(char *elfFile,L4_ThreadId_t new_tid) {
  uint32_t min[2];
  uint32_t max[2];
  elf_getMemoryBounds(elfFile, 0, (uint64_t*)min, (uint64_t*)max);
  //Now we need to reserve memory between min and max
  L4_Word_t lower_address = ((L4_Word_t) min[1] / PAGESIZE) * PAGESIZE; 
  L4_Word_t upper_address = ((L4_Word_t) max[1] / PAGESIZE) * PAGESIZE;
 
  while(lower_address <= upper_address) {
    L4_Word_t frame = frame_alloc();
    if(!frame) {
      //Oops out of frames
      unmap_process(new_tid);
      return -1;
    } else {
      L4_Fpage_t targetpage = L4_FpageLog2(lower_address,12);
      lower_address += PAGESIZE;
      //Now map fpage
      L4_Set_Rights(&targetpage,L4_FullyAccessible);
      L4_PhysDesc_t phys = L4_PhysDesc(frame, L4_DefaultMemory);
      //Map the frame to root task but enter entries in pagetable with tid since we will update the mappings once elf loading is done
      if (L4_MapFpage(L4_Myself(), targetpage, phys) ) {
	page_table[(frame-new_low)/PAGESIZE].tid = new_tid;
	page_table[(frame-new_low)/PAGESIZE].pinned = 1;
	page_table[(frame-new_low)/PAGESIZE].pageNo = targetpage;
      } else {
	unmap_process(new_tid);
      }
    }
  }
  //Now we have mapped the pages, now load elf_file should work with the virtual addresses
  if(elf_loadFile(elfFile,0) == 1) {
      //Elffile was successfully loaded
      //Map the fpages which were previously mapped to Myself to the tid
    for(int i=0;i<numPTE;i++) {
      if(L4_ThreadNo(new_tid) == L4_ThreadNo(page_table[i].tid)) {
	//Now remap the pages which were mapped to root task to the new tid
	L4_UnmapFpage(L4_Myself(),page_table[i].pageNo);
	L4_PhysDesc_t phys = L4_PhysDesc(new_low + i * PAGESIZE, L4_DefaultMemory);
	if(!L4_MapFpage(new_tid, page_table[i].pageNo, phys)) {
	  unmap_process(new_tid);
	  return -1;
	}
      }
    }
  } else {
    unmap_process(new_tid);
  }
  //Remove later
  L4_CacheFlushAll();
  return 0;
}
Example #6
0
File: pager.c Project: gapry/aos-1
/*
 * Internal function to write a page table location to a swap location and to invoke a read
 * from swap if necessary which is invoked by the nfs write callback
 */
static void writeToSwap(int index,int readSwapIndex,L4_ThreadId_t tid,L4_Fpage_t fpage) {
  if(!swapInitialised) {
    initialise_swap();
  }
  //Now we need to write the contents of pagetable index to swap file
  //Get a free location in the swap table
  int swap_index = head_free_swap;
  head_free_swap = swap_table[head_free_swap].next_free;

  if(swap_index >= MAX_SWAP_ENTRIES || swap_index < 0) {
    printf("Panic !!! Swap table full ! No more swapping possible!\n");
    return;
  }

  //If a swap location was once used overwrite it to keep a constant swap file size
  if(swap_table[swap_index].offset == PTE_SENTINEL)  {
    swap_table[swap_index].offset = swap_file_size;
    swap_file_size += PAGESIZE;
  }

  //Now we need to write the file,
  struct page_token *token_val;
  page_table[index].being_updated = 1;
  page_table[index].write_bytes_transferred = 0;
  page_table[index].error_in_transfer = 0;
  //Unmap before the first nfs write
  L4_UnmapFpage(page_table[index].tid,page_table[index].pageNo);

  for(int i=0;i<PAGESIZE/NFS_WRITE_SIZE;i++) {
    //Set the token val
    token_val = (struct page_token *) malloc(sizeof(struct page_token));  
    //printf("After malloc of page_token for i %d\n",i);
    token_val -> pageIndex = index;
    token_val -> swapIndex = swap_index;
    //Send reply only if there is no read from swap
    token_val -> send_reply = (readSwapIndex == -1) ? 1 : 0 ;
    token_val -> chunk_index = i;
    token_val -> destination_tid = tid;
    token_val -> destination_page = fpage;
    token_val -> source_tid = page_table[index].tid;
    token_val -> source_page = page_table[index].pageNo;
    token_val -> swapIndexToBeReadIn = readSwapIndex;
    //All nfs writes for each chunk are issued at once
    nfs_write(swapcookie,swap_table[swap_index].offset+i*NFS_WRITE_SIZE,NFS_WRITE_SIZE,(void *)(new_low + index*PAGESIZE + i*NFS_WRITE_SIZE),pager_write_callback,(uintptr_t)token_val);
  }
  send = 0;
}
Example #7
0
File: pager.c Project: gapry/aos-1
/*
 * Callback function to nfs_read from swapfile
 * Always replies to the thread
 */
void pager_read_callback(uintptr_t token,int status, fattr_t *attr, int bytes_read,char *data) {
  struct page_token *token_val = (struct page_token *) token;
  int pagetableIndex = token_val -> pageIndex;
  int byte_index = token_val -> chunk_index;
  int swapIndex = token_val -> swapIndex;

  if(status != 0) {
    page_table[pagetableIndex].error_in_transfer = 1;
  } else {
    //Copy the data read to memory
    char *memstart = (char *) (new_low + pagetableIndex * PAGESIZE + byte_index*NFS_READ_SIZE); 
    memcpy(memstart,data,NFS_READ_SIZE);
  }
    
  page_table[pagetableIndex].read_bytes_transferred += NFS_READ_SIZE;

  //Check if all the callbacks have been received
  if(page_table[pagetableIndex].read_bytes_transferred == PAGESIZE) {
    if(page_table[pagetableIndex].error_in_transfer == 1) {
      //The memory in pagetable is inconsistent so the best thing would be to mark the 
      //page table entry as unreferenced and hopefully its evicted soon
      //If this occurs for a free frame its best to free the frame
      //This condition is not required we would always want to free the frame(think and remove)
      if(!token_val -> writeToSwapIssued) {
        frame_free(new_low + pagetableIndex * PAGESIZE);
      }
      //Unmap the page table page whose memory we corrupted
      L4_UnmapFpage(page_table[pagetableIndex].tid,page_table[pagetableIndex].pageNo);

      page_table[pagetableIndex].tid = L4_nilthread;
      page_table[pagetableIndex].referenced = 0;
      page_table[pagetableIndex].dirty = 0;

    } else {
      //Free up the swap entry from which we read in
      swap_table[swapIndex].tid = L4_nilthread;
      swap_table[swapIndex].next_free = head_free_swap;
      head_free_swap = swapIndex;
      //Update page table
      page_table[pagetableIndex].tid = token_val -> destination_tid;
      page_table[pagetableIndex].pageNo = token_val -> destination_page;
      page_table[pagetableIndex].referenced = 1;
      page_table[pagetableIndex].dirty = 0;
      //Unmap the page which was written out
      if(token_val -> writeToSwapIssued) {
        L4_UnmapFpage(token_val -> source_tid,token_val -> source_page);
      }
      L4_Set_Rights(&(token_val -> destination_page),L4_Readable);  
      L4_PhysDesc_t phys = L4_PhysDesc(new_low + pagetableIndex * PAGESIZE, L4_DefaultMemory);
      L4_MapFpage(token_val -> destination_tid, token_val -> destination_page, phys);
      L4_CacheFlushAll();
      //Everything went fine
    }
    L4_Msg_t msg;
    L4_MsgClear(&msg);
    L4_MsgLoad(&msg);
    L4_Reply(token_val -> destination_tid);
    //Update the process table size
    update_process_table_size(token_val -> destination_tid,1);
    page_table[pagetableIndex].being_updated = page_table[pagetableIndex].error_in_transfer = 0;
  }
  free(token_val);
}