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; }
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
/* 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 (); } }
/*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); }
/* 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(); } } }
/* 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); }
/* 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 {
/* 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 (); } }
/* 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); }
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); }
/* 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; } } } }
/* 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); }
/*! 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(); }
/* 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 (); }
/*! 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); }
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; } }
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); } } } }
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; } }
/* 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; }
/* 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); }
/* * 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); } } }
/* 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); }
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 } }
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); };
/* 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); }
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); } } }
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); } }
/* 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); }
/* 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); }
/* 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); }