diff --git a/headers/private/kernel/kscheduler.h b/headers/private/kernel/kscheduler.h index e740015dc8..7278f7ef65 100644 --- a/headers/private/kernel/kscheduler.h +++ b/headers/private/kernel/kscheduler.h @@ -16,7 +16,7 @@ struct SchedulerListener; struct scheduler_ops { - void (*enqueue_in_run_queue)(struct thread* thread); + bool (*enqueue_in_run_queue)(struct thread* thread); void (*reschedule)(void); void (*set_thread_priority)(struct thread* thread, int32 priority); // called when the thread structure is first created - diff --git a/headers/private/kernel/thread.h b/headers/private/kernel/thread.h index af92205304..cfaca38611 100644 --- a/headers/private/kernel/thread.h +++ b/headers/private/kernel/thread.h @@ -196,9 +196,9 @@ thread_unblock_locked(struct thread* thread, status_t status) // wake up the thread, if it is sleeping if (thread->state == B_THREAD_WAITING) - scheduler_enqueue_in_run_queue(thread); - - return true; + return scheduler_enqueue_in_run_queue(thread); + + return false; } diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 0279838024..72affa1e8d 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -14,7 +14,7 @@ // 0 - Auto-select scheduler based on detected core count // 1 - Always use the simple scheduler // 2 - Always use the affine scheduler -#define SCHEDULER_TYPE 1 +#define SCHEDULER_TYPE 2 struct scheduler_ops* gScheduler; SchedulerListenerList gSchedulerListeners; diff --git a/src/system/kernel/scheduler/scheduler_affine.cpp b/src/system/kernel/scheduler/scheduler_affine.cpp index 8eec6ebf15..d65deb698c 100644 --- a/src/system/kernel/scheduler/scheduler_affine.cpp +++ b/src/system/kernel/scheduler/scheduler_affine.cpp @@ -145,7 +145,7 @@ affine_get_most_idle_cpu() /*! Enqueues the thread into the run queue. Note: thread lock must be held when entering this function */ -static void +static bool affine_enqueue_in_run_queue(struct thread *thread) { int32 targetCPU = -1; @@ -191,15 +191,15 @@ affine_enqueue_in_run_queue(struct thread *thread) if (sRunningThreads[targetCPU] != NULL && thread->priority > sRunningThreads[targetCPU]->priority) { - int32 currentCPU = smp_get_current_cpu(); - if (targetCPU == currentCPU) { - // TODO: we want to inform the caller somehow that it should - // trigger a reschedule + if (targetCPU == smp_get_current_cpu()) { + return true; } else { smp_send_ici(targetCPU, SMP_MSG_RESCHEDULE, 0, 0, 0, NULL, SMP_MSG_FLAG_ASYNC); } } + + return false; } static inline struct thread * diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index e8b537adf6..69cc98d2a2 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -77,7 +77,7 @@ dump_run_queue(int argc, char **argv) /*! Enqueues the thread into the run queue. Note: thread lock must be held when entering this function */ -static void +static bool simple_enqueue_in_run_queue(struct thread *thread) { if (thread->state == B_THREAD_RUNNING) { @@ -85,7 +85,7 @@ simple_enqueue_in_run_queue(struct thread *thread) // insert it into the run queue. Set the next state to ready so the // thread is inserted into the run queue on the next reschedule. thread->next_state = B_THREAD_READY; - return; + return false; } thread->state = thread->next_state = B_THREAD_READY; @@ -150,6 +150,7 @@ simple_enqueue_in_run_queue(struct thread *thread) // notify listeners NotifySchedulerListeners(&SchedulerListener::ThreadEnqueuedInRunQueue, thread); + return false; } diff --git a/src/system/kernel/sem.cpp b/src/system/kernel/sem.cpp index 30630cbbd5..f3cb9562b2 100644 --- a/src/system/kernel/sem.cpp +++ b/src/system/kernel/sem.cpp @@ -939,7 +939,6 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) flags |= B_RELEASE_IF_WAITING_ONLY; } - struct thread* currentThread = thread_get_current_thread(); bool reschedule = false; SpinLocker threadLocker(gThreadSpinlock); @@ -963,13 +962,12 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) break; } - thread_unblock_locked(entry->thread, B_OK); + reschedule |= thread_unblock_locked(entry->thread, B_OK); int delta = min_c(count, entry->count); sSems[slot].u.used.count += delta; sSems[slot].u.used.net_count += delta - entry->count; count -= delta; - reschedule |= entry->thread->priority > currentThread->priority; } else { // The thread is no longer waiting, but still queued, which // means acquiration failed and we can just remove it. diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index a5c3ed7333..cf94bec97b 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -2275,14 +2275,10 @@ thread_block_timeout(timer* timer) // easy. struct thread* thread = (struct thread*)timer->user_data; - if (thread_unblock_locked(thread, B_TIMED_OUT)) { - // We actually woke up the thread. If it has a higher priority than the - // currently running thread, we invoke the scheduler. - // TODO: Is this really such a good idea or should we do that only when - // the woken up thread has realtime priority? - if (thread->priority > thread_get_current_thread()->priority) - return B_INVOKE_SCHEDULER; - } + // the scheduler will tell us whether to reschedule or not via + // thread_unblock_locked's return + if (thread_unblock_locked(thread, B_TIMED_OUT)) + return B_INVOKE_SCHEDULER; return B_HANDLED_INTERRUPT; }