/* 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 (); } }
/* Called by the timer interrupt handler at each timer tick. Thus, this function runs in an external interrupt context. */ void thread_tick (void) { struct thread *t = thread_current (); /* Update statistics. */ if (t == idle_thread) idle_ticks++; #ifdef USERPROG else if (t->pagedir != NULL) user_ticks++; #endif else kernel_ticks++; /* Enforce preemption. */ if (++thread_ticks >= TIME_SLICE) intr_yield_on_return (); }
/* 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 thread *t=NULL; old_level = intr_disable (); if (!list_empty (&sema->waiters)) { struct list_elem *e=list_max(&sema->waiters, thread_max_priority,NULL); t= list_entry(e, struct thread, elem); list_remove(e); thread_unblock(t); //thread_unblock (list_entry (list_pop_front (&sema->waiters),struct thread, elem)); } sema->value++; intr_set_level (old_level); if(t && t->priority>thread_current()->priority){ if(intr_context()) intr_yield_on_return(); else thread_yield(); } }