Exemplo n.º 1
0
Arquivo: pid.c Projeto: gapry/os161
/*
 * Check whether ppid of a thread of given pid is the same as
 * the current thread's pid.
 * Returns -1 if such pid does not exist, 1 if comparison is true,
 * 0 otherwise.
 */
int
check_ppid(pid_t pid)
{
    struct pidinfo *my_pi;
    int retval;
    
    lock_acquire(pidlock);
    my_pi = pi_get(pid);
    
    if (my_pi == NULL) {
        return -1;
    } else if (my_pi->pi_ppid == curthread->t_pid) {
        retval = 1;
    } else {
        retval = 0;
    }
    
    lock_release(pidlock);
    return retval;
}
Exemplo n.º 2
0
/* Syscall handler for when a syscall read is invoked. */
static int read (int fd, void *buffer, unsigned length) {
  int size = -1;
  if (fd == STDIN_FILENO) {
    uint8_t *buffer_copy = (uint8_t *) buffer;
    unsigned i;
    for (i = 0; i < length; i++)
      buffer_copy[i] = input_getc();
    size = length;
  } else if (fd == STDOUT_FILENO) {
    size = -1;
  } else {
    struct file_wrapper *curr = fd_to_file_wrapper(fd);
    if (!curr)
      exit(-1);
    lock_acquire(&file_lock);
    size = file_read(curr->file, buffer, length);
    lock_release(&file_lock);
  }
  return size;
}
Exemplo n.º 3
0
/*
 * System Call: int write (int fd, const void *buffer, unsigned size)
 * Writes size bytes from buffer to the open file fd. Returns the number of
 * bytes actually written, which may be less than size if some bytes could
 * not be written.
 *
 * Writing past end-of-file would normally extend the file, but file growth
 * is not implemented by the basic file system. The expected behavior is to
 * write as many bytes as possible up to end-of-file and return the actual
 * number written, or 0 if no bytes could be written at all.
 *
 * Fd 1 writes to the console. Your code to write to the console should
 * write all of buffer in one call to putbuf(), at least as long as size
 * is not bigger than a few hundred bytes. (It is reasonable to break up
 * larger buffers.) Otherwise, lines of text output by different processes
 * may end up interleaved on the console, confusing both human readers and
 * our grading scripts.
 */
int write_handler(int fd, const void *buffer, unsigned size) {
	if (buffer_access_ok(buffer, size)) {
		if (fd == STDOUT_FILENO) {
			putbuf(buffer, size);
			return size;
		}
		lock_acquire (&fic_m);
		struct file* f = findfd(fd);
		if (f != NULL) {
			int ret = -1;
			if(!is_deny_write(f)){
				ret = file_write(f, buffer, size);
			}
			lock_release (&fic_m);
			return ret;
		}
		lock_release (&fic_m);
	}
	return -1;
}
Exemplo n.º 4
0
/* Syscall handler for when a syscall write is invoked. */
static int write (int fd, const void *buffer, unsigned size) {
  int bytes_written; 
  if (fd == STDOUT_FILENO) {
    putbuf(buffer, size);
    bytes_written = size;
  } else if (fd == STDIN_FILENO) {
    exit(-1);
  } else {
    struct file_wrapper *curr = fd_to_file_wrapper(fd);
    if (!curr) {
      exit(-1);
    } else {
      struct file *file = curr->file;
      lock_acquire(&file_lock);
      bytes_written = file_write(file, buffer, size);
      lock_release(&file_lock);
    }
  }
  return bytes_written;
}
Exemplo n.º 5
0
/* Opens the file with the name "file", and returns its file descriptor.
   Returns -1 if no such file exists, or if the open fails for any other
   reason.  If the same file is opened multiple times by separate processes
   or the same process, different fds with separate file pointers will be
   returned */
static int 
sys_open (const char *file)
{
  struct file *f;
  struct file_fd *ffd;
  check_ptr (file);
  
  lock_acquire (&fs_lock);
  f = filesys_open (file);
  lock_release (&fs_lock);

  if (f == NULL)
    return -1;
  ffd = malloc (sizeof(struct file_fd));
  ffd->file = f;
  ffd->fd = thread_current ()->next_fd++;
  list_push_back (&thread_current ()->open_files, &ffd->elem);

  return ffd->fd;
}
Exemplo n.º 6
0
/* Printf to the console. */
int
kprintf(const char *fmt, ...)
{
	int chars;
	va_list ap;

	if (kprintf_lock != NULL && !in_interrupt && curspl==0) {
		lock_acquire(kprintf_lock);
	}

	va_start(ap, fmt);
	chars = __vprintf(console_send, NULL, fmt, ap);
	va_end(ap);

	if (kprintf_lock != NULL && !in_interrupt && curspl==0) {
		lock_release(kprintf_lock);
	}

	return chars;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
/* Obtain a file's size. */
static int
sys_filesize (int fd)
{
  struct user_file *f;
  int size = -1;

#if PRINT_DEBUG
  printf ("[SYSCALL] SYS_FILESIZE: fd: %d\n", fd);
#endif

  f = file_by_fid (fd);
  if (f == NULL)
    return -1;

  lock_acquire (&file_lock);
  size = file_length (f->file);
  lock_release (&file_lock);

  return size;
}
Exemplo n.º 9
0
static void cache_read_ahead(void * cur_block)
{
	int lblock = *((int *)cur_block); 
	if(removed)
		return;
	if(find_cache(lblock) == NULL)
		if(lblock <= 0x2000)
		{
			struct cache* empty_cache = find_empty_cache();
			lock_acquire(&device_lock);
			block_read(fs_device, lblock, empty_cache->caddr);
			lock_release(&device_lock);

			empty_cache->used = true;
			empty_cache->sector = lblock;
			
		}
	free(cur_block);
	thread_exit();
}
/*!
 * @brief Poll a socket for data to recv and block when none available.
 * @param remote Pointer to the remote instance.
 * @param timeout Amount of time to wait before the poll times out (in milliseconds).
 * @return Indication of success or failure.
 */
static LONG server_socket_poll(Remote * remote, long timeout) {
	TcpTransportContext* ctx = (TcpTransportContext*)remote->transport->ctx;
	struct timeval tv;
	LONG result;
	fd_set fdread;

	lock_acquire(remote->lock);
	FD_ZERO(&fdread);
	FD_SET(ctx->fd, &fdread);
	tv.tv_sec = 0;
	tv.tv_usec = timeout;
	result = select((int)ctx->fd + 1, &fdread, NULL, NULL, &tv);

	if (result == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
		result = 0;
	}

	lock_release(remote->lock);
	return result;
}
Exemplo n.º 11
0
/* Report current position in a file. */
static unsigned
sys_tell (int fd)
{
  struct user_file *f;
  unsigned status;

#if PRINT_DEBUG
  printf ("[SYSCALL] SYS_TELL: fd: %d\n", fd);
#endif

  f = file_by_fid (fd);
  if (!f)
    sys_exit (-1);

  lock_acquire (&file_lock);
  status = file_tell (f->file);
  lock_release (&file_lock);

  return status;
}
Exemplo n.º 12
0
/* Close a file. */
static void
sys_close (int fd)
{
  struct user_file *f;

#if PRINT_DEBUG
  printf ("[SYSCALL] SYS_CLOSE: fd: %d\n", fd);
#endif

  f = file_by_fid (fd);

  if (f == NULL)
    sys_exit (-1);

  lock_acquire (&file_lock);
  list_remove (&f->thread_elem);
  file_close (f->file);
  free (f);
  lock_release (&file_lock);
}
Exemplo n.º 13
0
/* Reads the next directory entry in DIR and stores the name in
   NAME.  Returns true if successful, false if the directory
   contains no more entries. */
bool
dir_readdir (struct dir *dir, char name[NAME_MAX + 1])
{
  struct dir_entry e;

  bool result = false;
  lock_acquire (&dir->l);
  while (!result && 
      inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e) 
  {
    if (e.in_use)
    {
      strlcpy (name, e.name, NAME_MAX + 1);
      result = true;
    } 
    dir->pos += sizeof e;
  }
  lock_release (&dir->l);
  return result;
}
Exemplo n.º 14
0
void sysexit(int exit_code){
	pid_t pid = curthread->pid ;
	lock_acquire(process_table[pid]->exit_lock) ;
	process_table[pid]->exited = true ;
	process_table[pid]->exitcode=_MKWAIT_EXIT(exit_code);
	//close file descriptors
	int i=0;
	for(i=0;i<OPEN_MAX_LOCAL;i++){
		if(curthread->fd[i] != NULL)
		{
			sys_close((userptr_t)i);
		}

	}

	cv_broadcast(process_table[pid]->exit_cv,process_table[pid]->exit_lock) ;
	lock_release(process_table[pid]->exit_lock) ;

	thread_exit();
}
Exemplo n.º 15
0
/*
 * pid_exit 
 *  - sets the exit status of this thread (i.e. curthread). 
 *  - disowns children. 
 *  - if dodetach is true, children are also detached. 
 *  - wakes any thread waiting for the curthread to exit. 
 *  - frees the PID and exit status if the curthread has been detached. 
 *  - must be called only if the thread has had a pid assigned.
 */
void
pid_exit(int status, bool dodetach)
{
	struct pidinfo *my_pi;

	lock_acquire(pidlock);

	my_pi = pi_get(curthread->t_pid);
	KASSERT(my_pi != NULL);

	/* Thread has had a pid assigned */
       	KASSERT(my_pi->pi_pid == curthread->t_pid);

	my_pi->pi_exitstatus = status;
	my_pi->pi_exited = true;

	/* Disown children */
	int i;
	for (i = 0; i < PROCS_MAX; i++){
	  if (pidinfo[i] != NULL && pidinfo[i]->pi_ppid == my_pi->pi_pid){
	    pidinfo[i]->pi_ppid = INVALID_PID;
	    
	    if (dodetach){
	      pid_detach(pidinfo[i]->pi_pid);
	    }
	  }
	}

	/* Wake up all threads waiting for curthread to exit */
	if (my_pi->waitingThreads != 0){
	  cv_broadcast(my_pi->pi_cv, pidlock);
	}

	/* Free the PID and exit status if curthread is detached */
	if (my_pi->detached){
	  my_pi->pi_ppid = INVALID_PID;
	  pi_drop(my_pi->pi_pid);
	}
	
	lock_release(pidlock);
}
/*
 * core_channel_interact
 * ---------------------
 *
 * req: TLV_TYPE_CHANNEL_ID -- The channel identifier to interact with
 * req: TLV_TYPE_BOOL       -- True if interactive, false if not.
 */
DWORD remote_request_core_channel_interact(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	Channel *channel = NULL;
	DWORD channelId;
	DWORD result = ERROR_SUCCESS;
	BOOLEAN interact;

	// Get the channel identifier
	channelId = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_ID);
	interact  = packet_get_tlv_value_bool(packet, TLV_TYPE_BOOL);

	// If the channel is found, set the interactive flag accordingly
	if ((channel = channel_find_by_id(channelId)))
	{
		lock_acquire( channel->lock );

		// If the response packet is valid
		if ((response) &&
		    (channel_get_class(channel) != CHANNEL_CLASS_BUFFERED))
		{
			NativeChannelOps *native = (NativeChannelOps *)&channel->ops;

			// Check to see if this channel has a registered interact handler
			if (native->interact)
				result = native->interact(channel, packet, native->context, 
						interact);
		}

		// Set the channel's interactive state
		channel_set_interactive(channel, interact);

		lock_release( channel->lock );
	}

	// Send the response to the requestor so that the interaction can be 
	// complete
	packet_transmit_response(result, remote, response);

	return ERROR_SUCCESS;
}
Exemplo n.º 17
0
void
daemon_thread(void *data1, unsigned long data2)
{
	(void)data1;
	(void)data2;

	if (!USE_DAEMON) {
		cv_destroy(daemon.d_cv);
		lock_destroy(daemon.d_lock);
		return;
	}

	int allocated_pages;
	cme_id_t cme_id;
	struct cme *cme;

	cme_id = 0;

	while (true) {
		cme_id = (cme_id + 1) % coremap.cm_size;

		if (cm_attempt_lock(cme_id)) {
			cme = &coremap.cmes[cme_id];

			if (cme->cme_state == S_DIRTY) {
				cm_clean_page(cme_id);
			}

			cm_release_lock(cme_id);
		}

		allocated_pages = cm_get_page_count();
		if (allocated_pages <= daemon.d_memory_threshold) {
			lock_acquire(daemon.d_lock);
			daemon.d_awake = false;
			cv_wait(daemon.d_cv, daemon.d_lock);
			daemon.d_awake = true;
			lock_release(daemon.d_lock);
		}
	}
}
Exemplo n.º 18
0
void eat(const int creature_type) {
    /*
     * Convention: creature_type=0 -> cat. creature_type=1 -> mouse.
     */

    // Try to enter kitchen and potentially get blocked/grouped
    enter_kitchen(creature_type);

    // Choose a random initial bowl index
    unsigned int bowl = ((unsigned int)random() % NumBowls);
    int i = 0;

    for (i = 0; i < NumBowls; i++) {
        // Try to acquire it, but don't block if it is occupied
        if (lock_tryacquire(k->bowl_locks[bowl])) break;

        // Try another bowl
        bowl = (bowl+1) % NumBowls;
    }

    // If all the bowls are occupied
    if (i == NumBowls) {
        // Just wait to acquire the initially chosen one
        bowl %= NumBowls;
        lock_acquire(k->bowl_locks[bowl]);
    }

    assert(lock_do_i_hold(k->bowl_locks[bowl]));

    // Eat
    if (creature_type) {
        mouse_eat(bowl+1);
    } else {
        cat_eat(bowl+1);
    }

    // Release this bowl's lock
    lock_release(k->bowl_locks[bowl]);

    exit_kitchen();
}
Exemplo n.º 19
0
/* Adds a file named NAME to DIR, which must not already contain a
   file by that name.  The file's inode is in sector
   INODE_SECTOR.
   Returns true if successful, false on failure.
   Fails if NAME is invalid (i.e. too long) or a disk or memory
   error occurs. */
bool
dir_add (struct dir *dir, const char *name, block_sector_t inode_sector)
{
  struct dir_entry e;
  off_t ofs;
  bool success = false;

  ASSERT (dir != NULL);
  ASSERT (name != NULL);

  /* Check NAME for validity. */
  if (*name == '\0' || strlen (name) > NAME_MAX)
    return false;

  lock_acquire (&dir->l);

  /* Check that NAME is not in use. */
  if (lookup (dir, name, NULL, NULL))
    goto done;

  /* Set OFS to offset of free slot.
     If there are no free slots, then it will be set to the
     current end-of-file.
     
     inode_read_at() will only return a short read at end of file.
     Otherwise, we'd need to verify that we didn't get a short
     read due to something intermittent such as low memory. */
  for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
       ofs += sizeof e) 
    if (!e.in_use)
      break;

  /* Write slot. */
  e.in_use = true;
  strlcpy (e.name, name, sizeof e.name);
  e.inode_sector = inode_sector;
  success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
done:
  lock_release (&dir->l);
  return success;
}
Exemplo n.º 20
0
/* Opens specified file. Returns its file descriptor. Same file opened
   multiple times returns different file descriptors. A process has an
   independent set of file descriptors (files open in that process). fd = 0 is
   STDIN_FILENO, fd = 1 is STDOUT_FILENO - These are never returned here.
   If file could not be opened, -1 is returned. */
static int
sys_open(const char *file) 
{
  check_mem_ptr(file);

  if (file == NULL)
    sys_exit(ERROR);

  lock_acquire(&secure_file);

  struct file *fl = filesys_open(file);
  if (fl == NULL) 
  {
    lock_release(&secure_file);
    return FD_ERROR;
  }

  struct thread *t = thread_current();
  /* Freed in sys_close(). */
  struct proc_file *f = malloc(sizeof(struct proc_file));

  if (f == NULL)
    sys_exit(FD_ERROR);

  list_push_front(&t->files, &f->file_elem);
  f->file = fl;
  /* If file is currently being run as an executable in this process, we must
     not be able to write to it. */
  if (is_executable(file))
    file_deny_write(f->file);

  int file_descriptor = t->next_file_descriptor;
  f->fd = file_descriptor;
  /* Increment next_file_descriptor so that the next file to be
     opened has a different file descriptor. */
  t->next_file_descriptor++;

  lock_release(&secure_file);

  return file_descriptor;
}
Exemplo n.º 21
0
struct cached_block *
get_cached_block (block_sector_t sector, bool dirty)
{
  lock_acquire (&cache_lock);

  struct cached_block *cb = lookup_cache (sector);

  if (cb == NULL)
  {
    if (entry_count < MAX_CACHE_SIZE)
    {
      cb = (struct cached_block *) malloc (sizeof (struct cached_block));
      if (cb == NULL)
      {
        lock_release (&cache_lock);
        PANIC ("ERROR : Main and Cache memory full.");
      }
      cb->open = 0;
      entry_count++;
    }
    else
    {
      cb = evict_cache_block ();
      list_remove (&cb->elem);
    }
    cb->sector = sector;
    block_read (fs_device, sector, cb->data);
    cb->accessed = true;
    cb->open++;
    cb->dirty = dirty;
    list_push_back (&cache_list, &cb->elem);
  }
  else
  {
    cb->accessed = true;
    cb->open++;
    cb->dirty |= dirty;
  }
  lock_release (&cache_lock);
  return cb;
}
Exemplo n.º 22
0
int sys_read(int fd, void *buffer, unsigned size) {
  // memory validation : [buffer+0, buffer+size) should be all valid
  check_user((const uint8_t*) buffer);
  check_user((const uint8_t*) buffer + size - 1);

  lock_acquire (&filesys_lock);
  int ret;

  if(fd == 0) { // stdin
    unsigned i;
    for(i = 0; i < size; ++i) {
      if(! put_user(buffer + i, input_getc()) ) {
        lock_release (&filesys_lock);
        sys_exit(-1); // segfault
      }
    }
    ret = size;
  }
  else {
    // read from file
    struct file_desc* file_d = find_file_desc(thread_current(), fd, FD_FILE);

    if(file_d && file_d->file) {

#ifdef VM
      preload_and_pin_pages(buffer, size);
#endif

      ret = file_read(file_d->file, buffer, size);

#ifdef VM
      unpin_preloaded_pages(buffer, size);
#endif
    }
    else // no such file or can't open
      ret = -1;
  }

  lock_release (&filesys_lock);
  return ret;
}
Exemplo n.º 23
0
/* 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"); */
        if (PAL_USER && page_cnt == 1)
          {
            /* frame_evict ();
            page_idx = bitmap_scan_and_flip (pool->used_map, 0, page_cnt, false);
            pages = pool->base + PGSIZE * page_idx; */
          }
        else
          if (flags & PAL_ASSERT)
            PANIC ("palloc_get: out of pages");
    }
   
  return pages;
}
Exemplo n.º 24
0
void baby_bird(void)
{
		
	int sleep_time;

	do {
		// Don't try to eat until mama has filled the bowl
		/* This handles an issue where the bowl lock is released so that 
			mama can refill bowl, but other babies enter scheduler first
			and claim the lock. */
		while (food_in_bowl <= 0);
		kprintf("\nBaby bird acquiring bowl lock...\n");
		lock_acquire(bowl_lock); // Lock out other babies		 
		
		kprintf("Baby bird has acquired the lock.\n");
		kprintf("Baby bird is now eating...\n");
		food_in_bowl--; // eat a portion
		kprintf("%d worms remain.\n", food_in_bowl);

		if (food_in_bowl <=0)
		{
			kprintf("\nOut of food.\n");
						
			kprintf("Signalling mama...\n");
			cv_signal(mama, bowl_lock); // alert mama to refill
			kprintf("I told mama to refill the bowl...\n");
			kprintf("Releasing bowl lock...\n");
			lock_release(bowl_lock); // release the lock
		
		}
		else	
		{	
			kprintf("Baby bird is releasing the lock...\n");
			lock_release(bowl_lock); // Unlock the bowl
		}
		kprintf("Baby bird is sleeping...\n\n");
		sleep_time = random() % MAXSLEEP;
		clocksleep(sleep_time); // Sleep a random number of seconds
	} while (1);
	
}
Exemplo n.º 25
0
Arquivo: ide.c Projeto: YMChenLiye/os
//将buf中sec_cnt扇区数据写入硬盘
void ide_write(struct disk* hd,uint32_t lba,void* buf,uint32_t sec_cnt){
	ASSERT(lba <= max_lba);
	ASSERT(sec_cnt > 0);
	lock_acquire(&hd->my_channel->lock);

	//1、先选择操作的硬盘
	select_disk(hd);

	uint32_t secs_op;				//每此操作的扇区数
	uint32_t secs_done = 0;			//以完成的扇区数
	while(secs_done < sec_cnt){
		if((secs_done + 256) <= sec_cnt){
			secs_op = 256;
		}else{
			secs_op = sec_cnt - secs_done;
		}

		//2、写入待写入的扇区数和起始扇区号
		select_sector(hd,lba + secs_done , secs_op);

		//3、执行的命令写入reg_cmd寄存器
		cmd_out(hd->my_channel,CMD_WRITE_SECTOR);		//准备开始写数据

		//4、检测硬盘状态是否可读
		if(!busy_wait(hd)){				//若失败
			char error[64];
			sprintf(error,"%s write sector %d failed !!!!\n",hd->name,lba);
			PANIC(error);
		}

		//5、将数据写入硬盘
		write2sector(hd,(void*)((uint32_t)buf + secs_done * 512),secs_op);

		//在硬盘响应期间阻塞自己
		sema_down(&hd->my_channel->disk_done);
		secs_done += secs_op;
	}

	//醒来后开始释放锁
	lock_release(&hd->my_channel->lock);
}
Exemplo n.º 26
0
static
void
locktestthread(void *junk, unsigned long num)
{
	int i;
	(void)junk;

	for (i=0; i<NLOCKLOOPS; i++) {
		lock_acquire(testlock);
		testval1 = num;
		testval2 = num*num;
		testval3 = num%3;

		if (testval2 != testval1*testval1) {
			fail(num, "testval2/testval1");
		}

		if (testval2%3 != (testval3*testval3)%3) {
			fail(num, "testval2/testval3");
		}

		if (testval3 != testval1%3) {
			fail(num, "testval3/testval1");
		}

		if (testval1 != num) {
			fail(num, "testval1/num");
		}

		if (testval2 != num*num) {
			fail(num, "testval2/num");
		}

		if (testval3 != num%3) {
			fail(num, "testval3/num");
		}

		lock_release(testlock);
	}
	V(donesem);
}
Exemplo n.º 27
0
Arquivo: swap.c Projeto: Adam-Koza/A3
/*
 * swap_reserve/unreserve: reserve some pages for future allocation, or
 * release such pages.
 *
 * Synchronization: uses swaplock.
 */
int
swap_reserve(unsigned long npages)
{
	lock_acquire(swaplock);

	KASSERT(swap_free_pages <= swap_total_pages);
	KASSERT(swap_reserved_pages <= swap_free_pages);

	if (swap_free_pages - swap_reserved_pages < npages) {
		lock_release(swaplock);
		return ENOMEM;
	}

	swap_reserved_pages += npages;

	KASSERT(swap_free_pages <= swap_total_pages);
	KASSERT(swap_reserved_pages <= swap_free_pages);

	lock_release(swaplock);
	return 0;
}
Exemplo n.º 28
0
Arquivo: swap.c Projeto: Adam-Koza/A3
/*
 * swap_free: marks a page in the swapfile as unused.
 *
 * Synchronization: uses swaplock.
 */
void
swap_free(off_t swapaddr)
{
	uint32_t index;

	KASSERT(swapaddr != INVALID_SWAPADDR);
	KASSERT(swapaddr % PAGE_SIZE == 0);

	index = swapaddr / PAGE_SIZE;

	lock_acquire(swaplock);

	KASSERT(swap_free_pages < swap_total_pages);
	KASSERT(swap_reserved_pages <= swap_free_pages);

	KASSERT(bitmap_isset(swapmap, index));
	bitmap_unmark(swapmap, index);
	swap_free_pages++;

	lock_release(swaplock);
}
Exemplo n.º 29
0
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);
}
/* Creates a file named NAME with the given INITIAL_SIZE.
   Returns true if successful, false otherwise.
   Fails if a file named NAME already exists,
   or if internal memory allocation fails. */
bool
filesys_create (const char *name, off_t initial_size) 
{
  // XXX lock_acquire();
  lock_acquire(lock);
  // XXX
  block_sector_t inode_sector = 0;
  struct dir *dir = dir_open_root ();
  bool success = (dir != NULL
                  && free_map_allocate (1, &inode_sector)
                  && inode_create (inode_sector, initial_size)
                  && dir_add (dir, name, inode_sector));
  if (!success && inode_sector != 0) 
    free_map_release (inode_sector, 1);
  dir_close (dir);
  // XXX lock_release();
  lock_release(lock);
  // XXX

  return success;
}