Ejemplo n.º 1
0
static int32
rw_lock_unblock(rw_lock* lock)
{
	// Check whether there are any waiting threads at all and whether anyone
	// has the write lock.
	rw_lock_waiter* waiter = lock->waiters;
	if (waiter == NULL || lock->holder >= 0)
		return 0;

	// writer at head of queue?
	if (waiter->writer) {
		if (lock->active_readers > 0 || lock->pending_readers > 0)
			return 0;

		// dequeue writer
		lock->waiters = waiter->next;
		if (lock->waiters != NULL)
			lock->waiters->last = waiter->last;

		lock->holder = waiter->thread->id;

		// unblock thread
		thread_unblock(waiter->thread, B_OK);

		waiter->thread = NULL;
		return RW_LOCK_WRITER_COUNT_BASE;
	}

	// wake up one or more readers
	uint32 readerCount = 0;
	do {
		// dequeue reader
		lock->waiters = waiter->next;
		if (lock->waiters != NULL)
			lock->waiters->last = waiter->last;

		readerCount++;

		// unblock thread
		thread_unblock(waiter->thread, B_OK);

		waiter->thread = NULL;
	} while ((waiter = lock->waiters) != NULL && !waiter->writer);

	if (lock->count >= RW_LOCK_WRITER_COUNT_BASE)
		lock->active_readers += readerCount;

	return readerCount;
}
Ejemplo n.º 2
0
	 int unblock_max_priority_thd(struct list_elem *cur,int max_val,
									struct semaphore *sema)
	 {
		struct list_elem *max_priority_thd_elem;
		struct thread *max_priority_thd;
		
		for(cur = list_begin(&sema->waiters);cur!=list_end(&sema->waiters);
			cur=list_next(cur))
		{
			struct thread *cur_thd = list_entry (cur, struct thread, elem);
				int get_p=thread_highest_priority(cur_thd);
				if(max_val< get_p)
				{
					max_priority_thd_elem = cur;
					/* update the max priority */
					max_val=get_p;
					max_priority_thd=cur_thd;
				}//end of if
		}//end of for
		/* remove the thread from the list of waitlist in semaphore */
		list_remove(max_priority_thd_elem);
		/* now unblock this thread */
		thread_unblock(max_priority_thd);

		return max_val;
	 }//end of unblock_max_priority_thd function 
Ejemplo n.º 3
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 ();
  bool should_yield = false;
  if (!list_empty (&sema->waiters)) 
  {
    struct thread* t = list_entry (list_pop_front (&sema->waiters),
        struct thread, elem);
    should_yield = t->priority >= thread_current ()->priority;
    thread_unblock (t);
  }
  sema->value++;
  intr_set_level (old_level);

  /* Yield if higher priority thread in ready list */
  if (should_yield)
  {
    thread_yield ();
  }
}
Ejemplo n.º 4
0
/*our implements*/
void sema_up (struct semaphore *sema){
	enum intr_level old_level;
	ASSERT (sema!=NULL);
	old_level=intr_disable();

	sema->value ++ ;  //DON'T MOVE IT:this one seems must been put here

	//if sema do have waiting threads
	if (!list_empty(&sema->waiters))
	{
	  /*unblock the thread with the highest priority*/
	  /*PRE:before we sema_up,we call the sema_down, which this will always gives you a sorted list of waiters , highest priority first*/

	  //thread with highest priority
	  struct thread *max_t;
	  struct list_elem *e = list_min(&sema->waiters, higher_priority, NULL);
	  max_t = list_entry(e, struct thread, elem);

	  //remove it from the waiter list
	  list_remove(e);
	  thread_unblock(max_t);
	}

	intr_set_level(old_level);
}
Ejemplo n.º 5
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;
  struct thread *  tmp_t = thread_current();

  ASSERT (sema != NULL);
  old_level = intr_disable ();
  //unblock the higherst pri on the waiter list
  if (!list_empty (&sema->waiters)) 
  {
	  //printf("\nsema->waiters list size: %d\n", list_size(&sema->waiters));
	  struct list_elem *tmp_e = list_max((&sema->waiters), find_less_pri, NULL);
	  list_remove(tmp_e);
	  tmp_t = list_entry(tmp_e, struct thread, elem);
	  thread_unblock(tmp_t);
  }
                                
  sema->value++;
  intr_set_level (old_level);
  
  //if the curr thread doesnt have the highest anymore, yield
  if(thread_current() != tmp_t){
	  if (thread_get_priority() < get_pri(tmp_t)) 
	  { 
			thread_yield();
	  }
  }
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
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++;
    //int y=sema_value;
    if (!list_empty (&sema->waiters))
    {
        /*   //Original Code Starts
        thread_unblock (list_entry (list_pop_front (&sema->waiters),
                                 struct thread, elem));

            //Original Code Ends
        */
        //Finds Maximum Priority Thread Waiting on the lock
        struct list_elem *a1;
        struct thread* t;
        a1 = list_max( &sema->waiters, &(max_priority), 0 );
        t = list_entry (a1, struct thread, elem);
        printf ("Loc: Sema_Up %s\n", t->name );
        list_remove( a1 );
        //while(sema_value==y)
        sema->value++;
        thread_unblock( t );
    }
    else
    {
Ejemplo 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 ();
  }
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
void
mutex_destroy(mutex* lock)
{
	char* name = (lock->flags & MUTEX_FLAG_CLONE_NAME) != 0
		? (char*)lock->name : NULL;

	// unblock all waiters
	InterruptsSpinLocker locker(lock->lock);

#if KDEBUG
	if (lock->waiters != NULL && thread_get_current_thread_id()
		!= lock->holder) {
		panic("mutex_destroy(): there are blocking threads, but caller doesn't "
			"hold the lock (%p)", lock);
		if (_mutex_lock(lock, &locker) != B_OK)
			return;
		locker.Lock();
	}
#endif

	while (mutex_waiter* waiter = lock->waiters) {
		// dequeue
		lock->waiters = waiter->next;

		// unblock thread
		thread_unblock(waiter->thread, B_ERROR);
	}

	lock->name = NULL;

	locker.Unlock();

	free(name);
}
Ejemplo n.º 11
0
/* Checks the sleep_list's head element and if it needs
 * to be awoken, pops it from the sleep_list and unblocks the thread */
static void check_sleep_list (struct list *sleep_list) {
	// Ensures the sleep_list is not empty,
	if (!list_empty(&sleep_list)) {

		struct list_elem *current_elem = list_begin(sleep_list);

		while(current_elem != list_end(sleep_list)) {

			struct thread *current_thread = list_entry(current_elem, struct thread, elem);

			if(current_thread->awake_tick <= ticks) {

				list_pop_front(sleep_list);

				if(current_thread->status == THREAD_BLOCKED) {
					thread_unblock(current_thread);
				}

				current_elem = list_begin(sleep_list);

			} else {
				break;
			}
		}
	}
}
Ejemplo 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 ();
  if (!list_empty (&sema->waiters)) 
  {  
				
			struct list_elem * sema_waitlist_p = list_begin(&sema->waiters);
			struct list_elem * high = list_begin(&sema->waiters);
			for(;
			sema_waitlist_p != NULL && sema_waitlist_p->next != NULL && sema_waitlist_p->prev != NULL;)
			{
				if(list_entry(sema_waitlist_p, struct thread, elem)->priority >
				list_entry(high, struct thread, elem)->priority)
						high = sema_waitlist_p;
				sema_waitlist_p = list_next(sema_waitlist_p);
			}
			sema->current_holder = NULL;
			struct thread * t = list_entry(high, struct thread, elem);
			list_remove(high);
			thread_unblock (t);
	}
	sema->value++;
  intr_set_level (old_level);
}
Ejemplo n.º 13
0
/*!	You must call this function with interrupts disabled, and the semaphore's
	spinlock held. Note that it will unlock the spinlock itself.
	Since it cannot free() the semaphore's name with interrupts turned off, it
	will return that one in \a name.
*/
static void
uninit_sem_locked(struct sem_entry& sem, char** _name)
{
	KTRACE("delete_sem(sem: %ld)", sem.u.used.id);

	notify_sem_select_events(&sem, B_EVENT_INVALID);
	sem.u.used.select_infos = NULL;

	// free any threads waiting for this semaphore
	while (queued_thread* entry = sem.queue.RemoveHead()) {
		entry->queued = false;
		thread_unblock(entry->thread, B_BAD_SEM_ID);
	}

	int32 id = sem.id;
	sem.id = -1;
	*_name = sem.u.used.name;
	sem.u.used.name = NULL;

	RELEASE_SEM_LOCK(sem);

	// append slot to the free list
	GRAB_SEM_LIST_LOCK();
	free_sem_slot(id % sMaxSems, id + sMaxSems);
	atomic_add(&sUsedSems, -1);
	RELEASE_SEM_LIST_LOCK();
}
Ejemplo n.º 14
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) 
{
  bool yield = false;
  enum intr_level old_level;

  ASSERT (sema != NULL);

  old_level = intr_disable ();
  
  if (!list_empty (&sema->waiters))
    {
      struct thread *max = sema_pop_max_priority_waiter (sema);
      ASSERT (max != NULL);
      thread_unblock (max);

      //TODO: Why does commenting this line cause test mlfqs-block to pass?
      if (max->priority > thread_current ()->priority)
        yield = true;
    }

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

  if (yield)
    thread_yield ();
}
Ejemplo 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. */
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)) {
        struct list_elem *e = list_begin(&sema->waiters);
        struct thread *wake_thread = list_entry(e, struct thread, elem);
        int max_priority = compute_priority(wake_thread);

        for (e = list_next(e); e != list_end(&sema->waiters); 
             e = list_next(e)) { 
            struct thread *t = list_entry(e, struct thread, elem);
            int priority = compute_priority(t);
            if (priority > max_priority) { 
                max_priority = priority;
                wake_thread = t;
            }
        }

        list_remove(&wake_thread->elem);
        thread_unblock(wake_thread);
        if (max_priority >= thread_get_priority()) {
            thread_yield();
        } 

    }
    intr_set_level(old_level);
}
Ejemplo n.º 16
0
int sys_exec(char* filename)
{
  tid_t tid = process_execute(filename);
  if(tid == -1) // process execute failed, return -1
    return -1;
  else  // tid is valid
  {
    intr_disable();
    thread_block(); // block myself, until child wakes me up 
                    // with the exec_status, telling me if the elf load was successful
    intr_enable();

    struct thread* child = get_thread_from_tid(tid);
   
    if(child)
    {
      // exec_status will be -1 if load failed, hence we return -1
      // in such case
      tid = child->exec_status;
      child->parent_waiting_exec = 0;
      // child had blocked itself, unblock it
      thread_unblock(child);
    }
    return tid;
  }
}
Ejemplo n.º 17
0
static void wake_threads(struct thread *t, void *aux){
  if(t->status == THREAD_BLOCKED){
    if(t->sleep_ticks > 0){
      t->sleep_ticks--;
      if(t->sleep_ticks == 0){
        thread_unblock(t);
      }
    }
  }
}
Ejemplo n.º 18
0
	void Notify(status_t status = B_OK)
	{
		InterruptsSpinLocker _(fLock);
		TRACE("ReadRequest %p::Notify(), fNotified %d\n", this, fNotified);

		if (!fNotified) {
			thread_unblock(fThread, status);
			fNotified = true;
		}
	}
Ejemplo n.º 19
0
/* Creates a new kernel thread named NAME with the given initial
   PRIORITY, which executes FUNCTION passing AUX as the argument,
   and adds it to the ready queue.  Returns the thread identifier
   for the new thread, or TID_ERROR if creation fails.

   If thread_start() has been called, then the new thread may be
   scheduled before thread_create() returns.  It could even exit
   before thread_create() returns.  Contrariwise, the original
   thread may run for any amount of time before the new thread is
   scheduled.  Use a semaphore or some other form of
   synchronization if you need to ensure ordering.

   The code provided sets the new thread's `priority' member to
   PRIORITY, but no actual priority scheduling is implemented.
   Priority scheduling is the goal of Problem 1-3. */
tid_t
thread_create (const char *name, int priority,
               thread_func *function, void *aux) 
{
  struct thread *t;
  struct kernel_thread_frame *kf;
  struct switch_entry_frame *ef;
  struct switch_threads_frame *sf;
  tid_t tid;
  enum intr_level old_level;

  ASSERT (function != NULL);

  /* Allocate thread. */
  t = palloc_get_page (PAL_ZERO);
  if (t == NULL)
    return TID_ERROR;

  /* Initialize thread. */
  init_thread (t, name, priority);
  tid = t->tid = allocate_tid ();

  /* Prepare thread for first run by initializing its stack.
     Do this atomically so intermediate values for the 'stack' 
     member cannot be observed. */
  old_level = intr_disable ();

  /* Stack frame for kernel_thread(). */
  kf = alloc_frame (t, sizeof *kf);
  kf->eip = NULL;
  kf->function = function;
  kf->aux = aux;

  /* Stack frame for switch_entry(). */
  ef = alloc_frame (t, sizeof *ef);
  ef->eip = (void (*) (void)) kernel_thread;

  /* Stack frame for switch_threads(). */
  sf = alloc_frame (t, sizeof *sf);
  sf->eip = switch_entry;
  sf->ebp = 0;

  intr_set_level (old_level);

  /* Add to run queue. */
  thread_unblock (t);

  //we need to call thread yield now to check if this thread
  //has the highest priority
  thread_yield();

  return tid;
}
Ejemplo n.º 20
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 ();

    if (!list_empty (&sema->waiters)) {
        list_sort (&sema->waiters, (list_less_func *) &compare_priority, NULL);
        struct thread *waiter_thread = list_entry (list_pop_front (&sema->waiters),
                                       struct thread, elem);
        thread_unblock (waiter_thread);
    }
Ejemplo n.º 21
0
/*
 * This function checks if a thread needs to be unblocked
 * after waiting a certain amount of time
 */
void thread_wake(struct thread* t, void *aux)
{
  if (t->status == THREAD_BLOCKED && t->sleep_ticks > 0)
  {
    
    t->sleep_ticks--;
    //If this last decrement was the last tick, wake the thread.
    if(t->sleep_ticks == 0)
    {
      thread_unblock(t);
    }
  }
}
Ejemplo n.º 22
0
/* dismiss the alarm and unblock the thread */
static void
dismiss_alarm (struct alarm *alrm)
{
  enum intr_level old_level;
  
  ASSERT (is_alarm (alrm));
  
  /* remove from alarm_list, critical section */
  old_level = intr_disable ();
  list_remove (&alrm->elem);
  
  thread_unblock (alrm->thrd); /* unblock the thread */
  intr_set_level (old_level);
}
Ejemplo n.º 23
0
void
_mutex_unlock(mutex* lock)
{
	InterruptsSpinLocker locker(lock->lock);

#if KDEBUG
	if (thread_get_current_thread_id() != lock->holder) {
		panic("_mutex_unlock() failure: thread %" B_PRId32 " is trying to "
			"release mutex %p (current holder %" B_PRId32 ")\n",
			thread_get_current_thread_id(), lock, lock->holder);
		return;
	}
#else
	if (lock->ignore_unlock_count > 0) {
		lock->ignore_unlock_count--;
		return;
	}
#endif

	mutex_waiter* waiter = lock->waiters;
	if (waiter != NULL) {
		// dequeue the first waiter
		lock->waiters = waiter->next;
		if (lock->waiters != NULL)
			lock->waiters->last = waiter->last;
#if KDEBUG
		thread_id unblockedThread = waiter->thread->id;
#endif

		// unblock thread
		thread_unblock(waiter->thread, B_OK);

#if KDEBUG
		// Already set the holder to the unblocked thread. Besides that this
		// actually reflects the current situation, setting it to -1 would
		// cause a race condition, since another locker could think the lock
		// is not held by anyone.
		lock->holder = unblockedThread;
#endif
	} else {
		// We've acquired the spinlock before the locker that is going to wait.
		// Just mark the lock as released.
#if KDEBUG
		lock->holder = -1;
#else
		lock->flags |= MUTEX_FLAG_RELEASED;
#endif
	}
}
Ejemplo n.º 24
0
void 
sema_up (struct semaphore* sema)
{
    ASSERT (sema != NULL);

    enum interrupt_state state = interrupt_off ();
//    spinlock_acquire (&sema->sync);
    sema->val++;
    struct thread* t = LIST_ENTRY (
        list_pop_back (&sema->waiters), struct thread, elem);
//    spinlock_release (&sema->sync);

    thread_unblock (t);
    interrupt_restore (state);
};
Ejemplo n.º 25
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;
  struct thread * wakeup_thread = NULL;

  ASSERT (sema != NULL);

  old_level = intr_disable ();
  
  if (!list_empty (&sema->waiters)) {
    wakeup_thread = list_entry (list_pop_front (&sema->waiters),
    				struct thread, elem);
    thread_unblock (wakeup_thread);
  }
Ejemplo n.º 26
0
static void
check_for_ready_thread(struct thread *this_thread, void *aux)
{
 /*checking to make sure that the current thread is blocked and the timer is greater than 0*/
 if(this_thread->status == THREAD_BLOCKED && this_thread->wake_timer>0)
 {
 /*decrementing the thread's wake timer */
  this_thread->wake_timer--;
  /*Checking if it is time for the thread to wake up, if it is then it unblocks that thread*/
  if(this_thread->wake_timer == 0)
  {
   thread_unblock(this_thread);
  }
 }
}
Ejemplo n.º 27
0
Archivo: alarm.c Proyecto: nem0301/OS
void alarm_check(void) {
  struct alarm* al;
  enum intr_level old_level;


  old_level = intr_disable();

  if (!list_empty(&alarms)) {
    al = list_entry(list_begin(&alarms), struct alarm, elem);

    if (al->expiration < timer_ticks()) {
      list_remove(&al->elem);
      thread_unblock(al->th);
    }
  }
Ejemplo n.º 28
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 ();
  if (!list_empty (&sema->waiters)) {
    struct thread *t = list_entry (list_pop_front (&sema->waiters),
                                struct thread, elem);
    thread_unblock(t);
  }
  sema->value++;
  intr_set_level (old_level);
}
Ejemplo n.º 29
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);
	struct list_elem *e = NULL;
	struct thread *t;
  old_level = intr_disable ();
  if (!list_empty (&sema->waiters)) {
  list_sort(&sema->waiters, (list_less_func *) &higher_priority,
		NULL);
  	e = list_pop_front(&sema->waiters);
  	t = list_entry(e, struct thread, elem);
  	thread_unblock(t);
  }
Ejemplo n.º 30
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;
    struct thread *next_thread = NULL; 

    ASSERT (sema != NULL);

    old_level = intr_disable ();
    if (!list_empty (&sema->waiters)) 
    {
        list_sort(&sema->waiters, threadLessSort, NULL);

        next_thread = list_entry(list_pop_front(&sema->waiters), struct thread, elem);

        thread_unblock (next_thread);
    }