Esempio n. 1
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));
  
  enum intr_level old_state = intr_disable();
  // If there is lock holder
  // Add this thread to donorList of lock holder
  if (lock->holder != NULL)
  {
    // Save lock to this thread 
    thread_current()->tLock = lock;
    list_push_back(&lock->holder->donorList,&thread_current()->donorElem);
  }
  intr_set_level(old_state);

  sema_down (&lock->semaphore);
  // This thread is now the holder
  // Not waiting on any lock
  thread_current()->tLock = NULL;
  lock->holder = thread_current ();
  //intr_set_level(old_state);
}
Esempio n. 2
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  enum intr_level old_level;

  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));

  old_level = intr_disable ();

  if (lock->holder != NULL) 
    {
      /* Donate our priority to the thread holding the lock.
         First, update the data structures. */
      struct thread *donor = thread_current ();
      donor->want_lock = lock;
      donor->donee = lock->holder;
      list_push_back (&lock->holder->donors, &donor->donor_elem);
      
      /* Now implement the priority donation itself
         by recomputing the donee's priority
         and cascading the donation as far as necessary. */
      if (donor->donee != NULL)
        thread_recompute_priority (donor->donee);
    }

  sema_down (&lock->semaphore);
  lock->holder = thread_current ();
  intr_set_level (old_level);
}
Esempio n. 3
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));
  
  struct thread* acquirer = thread_current();
  
  if (!thread_mlfqs) {
  
    // P2: add new lock to the lock_list.
    if (!is_thread(lock->holder)) {
      // add lock into locklist.
      bool found = 0;
      int i;
      for (i=0;i<lock_list_cnt; i++)
        if (lock_list[i] == lock) found = 1;
      
      if (found == 0)  { 
        ASSERT (lock_list_cnt < 64);
        lock_list[lock_list_cnt++] = lock;
      }
    }
    lock_sema_down (&lock->semaphore, acquirer);
  } else {
    sema_down (&lock->semaphore);
  }
  // wait for the other to release
  lock->holder = acquirer;
}
Esempio n. 4
0
/* Down or "P" operation on a semaphore.  Waits for SEMA's value
 *   to become positive and then atomically decrements it.
 *
 *   This function may sleep, so it must not be called within an
 *   interrupt handler.  This function may be called with
 *   interrupts disabled, but if it sleeps then the next scheduled
 *   thread will probably turn interrupts back on. */
void sema_down(struct semaphore *sema) {
    enum intr_level old_level;

    ASSERT(sema != NULL);
    ASSERT(!intr_context());

    old_level = intr_disable ();

    while(sema -> value == 0) {
        /*
         * 注释掉原有代码
         * list_push_back(&sema->waiters, &thread_current ()->elem);
         */

        /* 按照降序插入 */
        list_insert_ordered(
                &sema -> waiters,
                &thread_current() -> elem,
                (list_less_func *) &priority_cmp_max_to_low,
                NULL
        );
        /* 阻塞当前线程 */
        thread_block();
    }

    sema -> value--;

    intr_set_level(old_level);
}
Esempio n. 5
0
/* Returns true if the current thread has the console lock,
   false otherwise. */
static bool
console_locked_by_current_thread (void) 
{
  return (intr_context ()
          || !use_console_lock
          || lock_held_by_current_thread (&console_lock));
}
Esempio n. 6
0
/* 
 --------------------------------------------------------------------
 Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. 
 NOTE: if we cannot aquire the lock and we are in regular priority
    donation scheduling, then we invoke the call to donate our
    priority. Once we move past the semaphore, we have aquired the 
    lock, and thus add it to our list of locks_held, so that this
    thread can properly recieve priortity donations. 
 --------------------------------------------------------------------
 */
void
lock_acquire (struct lock *lock)
{
    ASSERT (lock != NULL);
    ASSERT (!intr_context ());
    ASSERT (!lock_held_by_current_thread (lock));
    
    enum intr_level old_level = intr_disable();
    
    if (!thread_mlfqs) { 
        if (lock->holder != NULL) {
            thread_current()->lock_waiting_on = lock;
            //donate_priority();
        }
    }
    
    sema_down (&lock->semaphore);
    
    if (!thread_mlfqs) {
        lock->priority = PRI_MIN;
        list_push_front(&(thread_current()->locks_held), &(lock->elem));
        thread_current()->lock_waiting_on = NULL;
    }
    lock->holder = thread_current ();
    
    intr_set_level(old_level);
}
Esempio n. 7
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));
	
	struct thread *holder= lock->holder;
	
	/* If the current lock is already locked, then we update the mx_priority, by comparing it
	 * with the current_thread.
	 * We check if the thread holding the lock has less priority than the current priority so it
	 * donates it priority, then we add the current lock to the list of the thread of the donating_locks. */
	if(holder != NULL){
		if(lock->mx_priority < thread_current()->priority){
			lock->mx_priority= thread_current()->priority;
		}
		
		if(thread_current()->priority > holder->priority){
			if(!list_exist(&holder->donating_locks, &lock->elem)){
				list_push_back(&holder->donating_locks, &lock->elem);
			}
			holder->priority= thread_current()->priority;
		}
		
		thread_current()->blocked=lock;
		nest_donation(holder);
	}
	else{
		list_push_back(&thread_current()->donating_locks, &lock->elem);
	}
	
  sema_down (&lock->semaphore);
  lock->holder = thread_current();
}
Esempio n. 8
0
/* Up or "V" operation on a semaphore.  Increments SEMA's value
   and wakes up one thread of those waiting for SEMA, if any.

   This function may be called from an interrupt handler.
   Within an interrupt context, sema_up () always returns. */
void
sema_up (struct semaphore *sema) 
{
  enum intr_level old_level;
  bool yield = false;

  ASSERT (sema != NULL);

  old_level = intr_disable ();
  if (!list_empty (&sema->waiters)) 
  {
    struct thread *t = list_entry (list_pop_front (&sema->waiters),
                        struct thread, elem);
    thread_unblock (t);

    /* Yield to the newly unblocked thread if it has higher priority. */
    if (t->priority > thread_current ()->priority)
      yield = true;
  }
  sema->value++;
  intr_set_level (old_level);

  if (yield)
  {
    if (!intr_context ())
      thread_yield ();
    else
      intr_yield_on_return ();
  }
}
Esempio n. 9
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));

  enum intr_level old_level = intr_disable ();

  if (lock->holder != NULL) /* If the lock is being held. */
  {
    /* Updates current thread's lock_to_acquire attribute,
       adds itself to the lock holder's donors list and
       donates priority. */
    thread_current ()->lock_to_acquire = lock;
    list_push_front (&lock->holder->priority_donors,
                     &thread_current ()->donor);
    priority_donation ();
  }

  sema_down (&lock->semaphore);

  /* The lock has been acquired: current thread is not waiting
     for it anymore. */
  thread_current ()->lock_to_acquire = NULL;
  lock->holder = thread_current ();

  intr_set_level (old_level);
}
Esempio n. 10
0
File: synch.c Progetto: raunk/cs140
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));
  
  struct thread *cur_thread = thread_current ();

  /* If we are not in the multi-level feedback queue scheduler
     then use priority donation */
  if(!thread_mlfqs)
  {
    /* donate priority if someone holds the lock we want */
    enum intr_level old_level = intr_disable ();
     
    if (lock->holder != NULL) {
      cur_thread->lock_waiting_for = lock;
      cur_thread->t_donating_to = lock->holder;
      thread_donate_priority(cur_thread);
    }
    intr_set_level (old_level);
  }  

  sema_down (&lock->semaphore);
  lock->holder = cur_thread;
}
Esempio n. 11
0
bool 
grow_stack (void *uaddr)
{
  void *upage = pg_round_down (uaddr);
  if((size_t)(PHYS_BASE - upage) > (1 << 23)) return false;

  struct spage_table_entry *spte = malloc (sizeof (struct spage_table_entry));
  if (!spte) return false;
  spte->upage = upage;
  spte->in_memory = true;
  spte->writable = true;
  spte->spage_type = SWAP;
  spte->inevictable = true;

  uint8_t *f = frame_alloc (PAL_USER, spte);
  if (!f)
    {
      free (spte);
      return false;
    }

  if (!install_page (spte->upage, f, spte->writable))
    {
      free (spte);
      frame_free (f);
      return false;
    }

  if (intr_context ()) spte->inevictable = false;

  return hash_insert (&thread_current ()->spage_table, &spte->elem) == NULL;
}
Esempio n. 12
0
/* Up or "V" operation on a semaphore.  Increments SEMA's value
   and wakes up one thread of those waiting for SEMA, if any.

   This function may be called from an interrupt handler. */
void
sema_up (struct semaphore *sema) 
{
  enum intr_level old_level;

  ASSERT (sema != NULL);

  old_level = intr_disable ();
  sema->value++;
  if (!list_empty (&sema->waiters)) 
    {
      /* Find highest-priority waiting thread. */
      struct thread *max = list_entry (list_max (&sema->waiters,
                                                 thread_lower_priority, NULL),
                                       struct thread, elem);

      /* Remove `max' from wait list and unblock. */
      list_remove (&max->elem);
      thread_unblock (max);

      /* Yield to a higher-priority thread, if we're running in a
         context where it makes sense to do so.
         
         Kind of a funny interaction with donation here.
         We only support donation for locks, and locks turn off
         interrupts before calling us, so we automatically don't
         do the yield here, delegating to lock_release(). */
      if (!intr_context () && old_level == INTR_ON)
        thread_yield_to_higher_priority ();
    }
  intr_set_level (old_level);
}
Esempio n. 13
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));
  ASSERT (thread_current ()->waiting_on == NULL);

  enum intr_level old_level;
  old_level = intr_disable ();
  
  /* If the lock is currently held by someone, then we need to invoke
     thread_donate_priority to donate our priority to that special
     someone. */  
  if (!thread_mlfqs && lock->holder != NULL)
    {
      thread_current ()->waiting_on = lock;
      thread_donate_priority (thread_current ());
    }

  sema_down (&lock->semaphore);

  lock->holder = thread_current ();
  thread_current ()->waiting_on = NULL;

  intr_set_level (old_level);
}
Esempio n. 14
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));

  /* If the lock is not being held, just grap the lock. */
  if (lock->holder == NULL)
  {
    sema_down (&lock->semaphore);
    lock->holder = thread_current ();
  }
  /* If the lock is being held and donation is needed (priority is higher than the lock holder), 
  apply donation, set the lock holder as waiting thread and reverse donation afterwards. */
  else if (thread_current ()->priority > lock->holder->original_priority)
  {
    thread_current ()->thread_waiting_for = lock->holder;
    apply_donation (thread_current ());
    sema_down (&lock->semaphore);
    lock->holder = thread_current ();
    recover_priority (thread_current ()->thread_waiting_for);
  }
  /* If the lock is being held and donation is not needed (priority is lower than the lock holder), 
  just set the lock holder as waiting thread for possible chain donation and reverse possible chain donation afterwards */
  else
  {
    thread_current ()->thread_waiting_for = lock->holder;
    sema_down (&lock->semaphore);
    lock->holder = thread_current ();
  }
}
Esempio n. 15
0
/* Up or "V" operation on a semaphore.  Increments SEMA's value
   and wakes up one thread of those waiting for SEMA, if any.

   This function may be called from an interrupt handler. 

   The thread with the highest priority in the waiting list gets added
   to the ready_list. If it has a higher priority than the    
   running thread, then the running thread will be preempted. */
void
sema_up (struct semaphore *sema) 
{
  enum intr_level old_level;

  ASSERT (sema != NULL);

  old_level = intr_disable ();
  struct thread *t = NULL;

  if (!list_empty (&sema->waiters)) 
  {
    struct list_elem *next = list_max(&sema->waiters, list_comp_greater, 0);
    list_remove(next);
    t = list_entry (next, struct thread, elem);
    thread_unblock (t);
  }
   
  sema->value++;
  if(t != NULL && !intr_context()) 
  {
    check_preempt(t, false);
  }
  intr_set_level (old_level);
}
Esempio n. 16
0
/* Down or "P" operation on a semaphore.  Waits for SEMA's value
 *  to become positive and then atomically decrements it.
 *
 *  This function may sleep, so it must not be called within an
 *  interrupt handler.  This function may be called with
 *  interrupts disabled, but if it sleeps then the next scheduled
 *  thread will probably turn interrupts back on. */
void sema_down(struct semaphore *sema) {
    enum intr_level old_level;

    ASSERT(sema != NULL);
    ASSERT(!intr_context());

    old_level = intr_disable();
    while (sema -> value == 0) {
        /*
         * 注释掉原有的代码
         * list_push_back(&sema -> waiters, &thread_current() -> elem);
         * thread_block();
         */

        if (!thread_mlfqs) {
            donate_priority();
        }

        list_insert_ordered(
                &sema -> waiters,
                &thread_current() -> elem,
                (list_less_func *) &cmp_priority,
                NULL
        );
        thread_block();
    }

    sema -> value--;
    intr_set_level(old_level);
}
Esempio n. 17
0
/* Down or "P" operation on a semaphore.  Waits for SEMA's value
   to become positive and then atomically decrements it.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but if it sleeps then the next scheduled
   thread will probably turn interrupts back on. */
void
sema_down (struct semaphore *sema) 
{
  enum intr_level old_level;

  ASSERT (sema != NULL);
  ASSERT (!intr_context ());

  old_level = intr_disable ();

  struct thread *currentThread = thread_current();
  
  while (sema->value == 0) 
  {
  	if(!thread_mlfqs)
  	{
  	  thread_donate_priority();
  	}
  	//list_insert_priority_ordered (&sema->waiters, &currentThread->elem, currentThread->priority);
  	list_insert_ordered (&sema->waiters, &currentThread->elem, (list_less_func *) &thread_cmp_priority, NULL);

    thread_block ();
  }
  
  sema->value--;
  intr_set_level (old_level);
}
Esempio n. 18
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));

  //implementing donation
  //enum intr_level old_level;
  //old_level = intr_disable();

  //PRE:1.HIGHEST PRIORITY THREADS TAKING THE CPU
  //2.CURRENT->THREAD WHICH HAVE HIGHEST PRIORITY
  //3.Thus the lock holder must be in the ready list

  //NEW
  if (thread_mlfqs)
  { //roozbeh
	//in case mlfqs, no need for donations
    sema_down (&lock->semaphore);
    lock->holder = thread_current ();
  }
  else
  {
	//non- mlfqs case, do donation
	//duc:
    struct thread *cur = thread_current();
    struct thread *lock_holder = lock->holder;

    if (lock_holder != NULL)
	    donate(lock, cur->priority, MAX_DEPTH);

    //stick lock to current thread
    cur->target_lock = lock;
    sema_down(&lock->semaphore);
    lock->holder = thread_current();

    lock->max_priority = cur->priority;
    list_insert_ordered(&cur->lock_list, &lock->elem, higher_priority_lock, NULL);
    cur->target_lock = NULL;
  }
  //OLD
  /*if (lock_holder!=NULL && lock_holder->priority < cur->priority)
  {
    cur->donee_priority = lock_holder->priority;
    //insert into this lock's waiting queue according to it's priority
	//list_insert_ordered(&lock->semaphore.waiters, &cur->elem, higher_priority, NULL);
	//lock_holder->donation_times++; //>do we check donation_time initialized as 0?
	lock_holder->priority=cur->priority;

	//thread_block();
  }
  sema_down (&lock->semaphore);//try to release the lock
  lock->holder = thread_current ();*/

  //intr_set_level(old_level);
}
Esempio n. 19
0
/* Puts the current thread to sleep.  It will not be scheduled
   again until awoken by thread_unblock().

   This function must be called with interrupts turned off.  It
   is usually a better idea to use one of the synchronization
   primitives in synch.h. */
void
thread_block (void) 
{
  ASSERT (!intr_context ());
  ASSERT (intr_get_level () == INTR_OFF);

  thread_current ()->status = THREAD_BLOCKED;
  schedule ();
}
Esempio n. 20
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));

  sema_down (&lock->semaphore);
  lock->holder = thread_current ();
}
Esempio n. 21
0
/* Acquires the console lock. */
static void
acquire_console (void) 
{
  if (!intr_context () && use_console_lock) 
    {
      if (lock_held_by_current_thread (&console_lock)) 
        console_lock_depth++; 
      else
        lock_acquire (&console_lock); 
    }
}
Esempio n. 22
0
/* Releases the console lock. */
static void
release_console (void) 
{
  if (!intr_context () && use_console_lock) 
    {
      if (console_lock_depth > 0)
        console_lock_depth--;
      else
        lock_release (&console_lock); 
    }
}
Esempio n. 23
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));

  sema_down (&lock->semaphore);
  struct thread *cur = thread_current();
  list_push_back (&cur->holding_list, &lock->leHolder);
  lock->holder = thread_current ();
}
Esempio n. 24
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));

  if (!lock_try_acquire (lock)) /* Someone else holding the lock. */
  {
    sema_down (&lock->semaphore);
    lock->holder = thread_current ();
  }
}
Esempio n. 25
0
/*! Down or "P" operation on a semaphore.  Waits for SEMA's value
    to become positive and then atomically decrements it.

    This function may sleep, so it must not be called within an
    interrupt handler.  This function may be called with
    interrupts disabled, but if it sleeps then the next scheduled
    thread will probably turn interrupts back on. */
void sema_down(struct semaphore *sema) {
    enum intr_level old_level;

    ASSERT(sema != NULL);
    ASSERT(!intr_context());

    old_level = intr_disable();
    while (sema->value == 0) {
        list_push_back(&sema->waiters, &thread_current()->elem);
        thread_block();
    }
    sema->value--;
    intr_set_level(old_level);
}
Esempio n. 26
0
/*! Atomically releases LOCK and waits for COND to be signaled by
    some other piece of code.  After COND is signaled, LOCK is
    reacquired before returning.  LOCK must be held before calling
    this function.

    The monitor implemented by this function is "Mesa" style, not
    "Hoare" style, that is, sending and receiving a signal are not
    an atomic operation.  Thus, typically the caller must recheck
    the condition after the wait completes and, if necessary, wait
    again.

    A given condition variable is associated with only a single
    lock, but one lock may be associated with any number of
    condition variables.  That is, there is a one-to-many mapping
    from locks to condition variables.

    This function may sleep, so it must not be called within an
    interrupt handler.  This function may be called with
    interrupts disabled, but interrupts will be turned back on if
    we need to sleep. */
void cond_wait(struct condition *cond, struct lock *lock) {
    struct semaphore_elem waiter;

    ASSERT(cond != NULL);
    ASSERT(lock != NULL);
    ASSERT(!intr_context());
    ASSERT(lock_held_by_current_thread(lock));
  
    waiter.thread = thread_current();
    sema_init(&waiter.semaphore, 0);
    list_push_back(&cond->waiters, &waiter.elem);
    lock_release(lock);
    sema_down(&waiter.semaphore);
    lock_acquire(lock);
}
Esempio n. 27
0
	/* Acquires LOCK, sleeping until it becomes available if
	   necessary.  The lock must not already be held by the current
	   thread.And also it will take care of the donation of priority.

	   This function may sleep, so it must not be called within an
	   interrupt handler.  This function may be called with
	   interrupts disabled, but interrupts will be turned back on if
	   we need to sleep. */
	void
	lock_acquire (struct lock *lock)
	{
	  ASSERT (lock != NULL);
	  ASSERT (!intr_context ());
	  ASSERT (!lock_held_by_current_thread (lock));
	  enum intr_level old_level;
	  old_level = intr_disable ();
	  /* call a function that will check if the thread 
		 can donate its priority */
	  check_for_donation(lock);	
	  intr_set_level(old_level);
	  sema_down (&lock->semaphore);
	  lock->holder = thread_current ();
	}//end of lock_accquire function
Esempio n. 28
0
/* Adds BYTE to the end of Q.
   Q must not be full if called from an interrupt handler.
   Otherwise, if Q is full, first sleeps until a byte is
   removed. */
void
intq_putc (struct intq *q, uint8_t byte) 
{
  ASSERT (intr_get_level () == INTR_OFF);
  while (intq_full (q))
    {
      ASSERT (!intr_context ());
      lock_acquire (&q->lock);
      wait (q, &q->not_full);
      lock_release_with_preemption (&q->lock);
    }

  q->buf[q->head] = byte;
  q->head = next (q->head);
  signal (q, &q->not_empty);
}
Esempio n. 29
0
/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock)
{
  ASSERT (lock != NULL);
  ASSERT (!intr_context ());
  ASSERT (!lock_held_by_current_thread (lock));
  // Check for priority donation  
  struct thread *current_thread = thread_current();
  enum intr_level level = intr_disable();
  if(lock->holder!=NULL && lock->holder->priority < current_thread->priority){
    lock->holder->priority = current_thread->priority;
  }
  intr_set_level(level);
  sema_down (&lock->semaphore);
  lock->holder = current_thread;
}
Esempio n. 30
0
/*yan*/
void
sema_down (struct semaphore *sema) {
	enum intr_level old_level;
	ASSERT (sema != NULL);
	ASSERT (!intr_context ());
	old_level = intr_disable(); //disable the interrupts

	while (sema->value==0)
	{
	  //insert current thread into waiter list
	  list_insert_ordered(&sema->waiters,&thread_current()->elem,higher_priority,NULL);
	  thread_block();
	}

	sema->value--;
	intr_set_level (old_level);
}