added 8 changesets to branch 'refs/remotes/pdziepak-github/scheduler' old head: 03e3a8295375a672734943bcaa489ad09b22ac35 new head: 879ceb60d824345ff90f2f1d6a1e22a086dbe29f overview: https://github.com/pdziepak/Haiku/compare/03e3a82...879ceb6 ---------------------------------------------------------------------------- 94f4574: kernel: Move thread retrieving code to separate function 346e789: kernel: Fix style issues 9363e99: kernel: Remove Thread::next_priority ee69e53: kernel: Minor improvements, separate priority and yield logic 0896565: kernel: Support sched_yield() properly sched_yield() should not yield to the threads with lower priority. f256b4a: kernel: Use SimpleRunQueue as run queue type everywhere 130000e: kernel: Dump scheduler specific thread data 879ceb6: kernel: Remove suporfluous casts [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 5 files changed, 157 insertions(+), 144 deletions(-) headers/private/kernel/thread_types.h | 4 +- src/system/kernel/scheduler/scheduler_affine.cpp | 11 +- src/system/kernel/scheduler/scheduler_simple.cpp | 225 ++++++++++--------- .../kernel/scheduler/scheduler_simple_smp.cpp | 11 +- src/system/kernel/thread.cpp | 50 ++--- ############################################################################ Commit: 94f4574d78aca6445d60c0c04105f91b1ff01558 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 18:13:10 2013 UTC kernel: Move thread retrieving code to separate function ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index db51e53..2cafe65 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -346,6 +346,35 @@ static inline bigtime_t simple_compute_quantum(Thread* thread) } +static inline Thread* +simple_get_next_thread(void) +{ + Thread* thread; + do { + thread = sRunQueue->PeekMaximum(); + + if (sYieldedThreadPriority >= 0 && thread != NULL + && thread_is_idle_thread(thread)) { + sRunQueue->Remove(thread); + simple_enqueue_in_run_queue(thread); + continue; + } + + break; + } while (true); + if (thread == NULL && sYieldedThreadPriority >= 0) { + SimpleRunQueue* temp = sRunQueue; + sRunQueue = sExpiredQueue; + sExpiredQueue = temp; + sYieldedThreadPriority = -1; + + thread = sRunQueue->PeekMaximum(); + } + + return thread; +} + + /*! Runs the scheduler. Note: expects thread spinlock to be held */ @@ -353,7 +382,6 @@ static void simple_reschedule(void) { Thread* oldThread = thread_get_current_thread(); - Thread* nextThread; // check whether we're only supposed to reschedule, if the current thread // is idle @@ -417,29 +445,9 @@ simple_reschedule(void) schedulerOldThreadData->lost_cpu = false; // select thread with the biggest priority - do { - nextThread = sRunQueue->PeekMaximum(); - - if (sYieldedThreadPriority >= 0 && nextThread != NULL - && thread_is_idle_thread(nextThread)) { - sRunQueue->Remove(nextThread); - simple_enqueue_in_run_queue(nextThread); - continue; - } - - break; - } while (true); - if (nextThread == NULL && sYieldedThreadPriority >= 0) { - RunQueue<Thread, THREAD_MAX_SET_PRIORITY>* temp = sRunQueue; - sRunQueue = sExpiredQueue; - sExpiredQueue = temp; - sYieldedThreadPriority = -1; - - nextThread = sRunQueue->PeekMaximum(); - } + Thread* nextThread = simple_get_next_thread(); if (!nextThread) - panic("reschedule(): run queue is empty!\n"); - + panic("reschedule(): run queues are empty!\n"); sRunQueue->Remove(nextThread); T(ScheduleThread(nextThread, oldThread)); ############################################################################ Commit: 346e789a21882595ca008f58303ab76787691dc7 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 18:15:21 2013 UTC kernel: Fix style issues ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index 2cafe65..3601c0a 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -92,7 +92,7 @@ dump_queue(RunQueue<Thread, THREAD_MAX_SET_PRIORITY>::ConstIterator& iterator) else { kprintf("thread id priority penalty name\n"); while (iterator.HasNext()) { - Thread *thread = iterator.Next(); + Thread* thread = iterator.Next(); scheduler_thread_data* schedulerThreadData = reinterpret_cast<scheduler_thread_data*>( thread->scheduler_data); @@ -105,7 +105,7 @@ dump_queue(RunQueue<Thread, THREAD_MAX_SET_PRIORITY>::ConstIterator& iterator) static int -dump_run_queue(int argc, char **argv) +dump_run_queue(int argc, char** argv) { RunQueue<Thread, THREAD_MAX_SET_PRIORITY>::ConstIterator iterator; kprintf("Current run queue:\n"); @@ -129,7 +129,7 @@ simple_yield(Thread* thread) static inline int32 -simple_get_effective_priority(Thread *thread) +simple_get_effective_priority(Thread* thread) { if (thread->priority == B_IDLE_PRIORITY) return thread->priority; @@ -157,7 +157,7 @@ simple_get_effective_priority(Thread *thread) static inline void -simple_increase_penalty(Thread *thread) +simple_increase_penalty(Thread* thread) { if (thread->priority <= B_LOWEST_ACTIVE_PRIORITY) return; @@ -181,7 +181,7 @@ simple_increase_penalty(Thread *thread) static inline void -simple_cancel_penalty(Thread *thread) +simple_cancel_penalty(Thread* thread) { scheduler_thread_data* schedulerThreadData = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); @@ -200,7 +200,7 @@ simple_cancel_penalty(Thread *thread) Note: thread lock must be held when entering this function */ static void -simple_enqueue_in_run_queue(Thread *thread) +simple_enqueue_in_run_queue(Thread* thread) { thread->state = thread->next_state = B_THREAD_READY; @@ -243,7 +243,7 @@ simple_enqueue_in_run_queue(Thread *thread) Note: thread lock must be held when entering this function */ static void -simple_set_thread_priority(Thread *thread, int32 priority) +simple_set_thread_priority(Thread* thread, int32 priority) { if (priority == thread->priority) return; @@ -290,7 +290,7 @@ simple_estimate_max_scheduling_latency(Thread* thread) static int32 -reschedule_event(timer *unused) +reschedule_event(timer* /* unused */) { // This function is called as a result of the timer event set by the // scheduler. Make sure the reschedule() is invoked. ############################################################################ Commit: 9363e99b19d122db7d6684b06d7240fb73255cd2 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 18:21:35 2013 UTC kernel: Remove Thread::next_priority ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 637c5be..3e4ec90 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -422,7 +422,6 @@ struct Thread : TeamThreadIteratorEntry<thread_id>, KernelReferenceable, timer alarm; // protected by scheduler lock char name[B_OS_NAME_LENGTH]; // protected by fLock int32 priority; // protected by scheduler lock - int32 next_priority; // protected by scheduler lock int32 io_priority; // protected by fLock int32 state; // protected by scheduler lock int32 next_state; // protected by scheduler lock diff --git a/src/system/kernel/scheduler/scheduler_affine.cpp b/src/system/kernel/scheduler/scheduler_affine.cpp index 059df02..f5b7294 100644 --- a/src/system/kernel/scheduler/scheduler_affine.cpp +++ b/src/system/kernel/scheduler/scheduler_affine.cpp @@ -154,7 +154,7 @@ affine_enqueue_in_run_queue(Thread *thread) } else { Thread *curr, *prev; for (curr = sRunQueue[targetCPU], prev = NULL; curr - && curr->priority >= thread->next_priority; + && curr->priority >= thread->priority; curr = curr->queue_next) { if (prev) prev = prev->queue_next; @@ -173,8 +173,6 @@ affine_enqueue_in_run_queue(Thread *thread) thread->scheduler_data->fLastQueue = targetCPU; } - thread->next_priority = thread->priority; - // notify listeners NotifySchedulerListeners(&SchedulerListener::ThreadEnqueuedInRunQueue, thread); @@ -304,7 +302,7 @@ affine_set_thread_priority(Thread *thread, int32 priority) thread = dequeue_from_run_queue(prev, targetCPU); // set priority and re-insert - thread->priority = thread->next_priority = priority; + thread->priority = priority; affine_enqueue_in_run_queue(thread); } diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index 3601c0a..99818d8 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -152,7 +152,7 @@ simple_get_effective_priority(Thread* thread) ASSERT(schedulerThreadData->priority_penalty >= 0); ASSERT(effectivePriority >= B_LOWEST_ACTIVE_PRIORITY); - return min_c(effectivePriority, thread->next_priority); + return effectivePriority; } @@ -217,7 +217,6 @@ simple_enqueue_in_run_queue(Thread* thread) else sRunQueue->PushBack(thread, threadPriority); - thread->next_priority = thread->priority; schedulerThreadData->cpu_bound = true; schedulerThreadData->time_left = 0; schedulerThreadData->stolen_time = 0; @@ -267,7 +266,7 @@ simple_set_thread_priority(Thread* thread, int32 priority) // set priority and re-insert simple_cancel_penalty(thread); - thread->priority = thread->next_priority = priority; + thread->priority = priority; simple_enqueue_in_run_queue(thread); } diff --git a/src/system/kernel/scheduler/scheduler_simple_smp.cpp b/src/system/kernel/scheduler/scheduler_simple_smp.cpp index 6665612..092fd70 100644 --- a/src/system/kernel/scheduler/scheduler_simple_smp.cpp +++ b/src/system/kernel/scheduler/scheduler_simple_smp.cpp @@ -118,7 +118,7 @@ enqueue_in_run_queue(Thread *thread) Thread *curr, *prev; for (curr = sRunQueue, prev = NULL; curr - && curr->priority >= thread->next_priority; + && curr->priority >= thread->priority; curr = curr->queue_next) { if (prev) prev = prev->queue_next; @@ -134,8 +134,6 @@ enqueue_in_run_queue(Thread *thread) else sRunQueue = thread; - thread->next_priority = thread->priority; - if (thread->priority != B_IDLE_PRIORITY) { // Select a CPU for the thread to run on. It's not certain that the // thread will actually run on it, but we will notify the CPU to @@ -211,7 +209,7 @@ set_thread_priority(Thread *thread, int32 priority) sRunQueue = item->queue_next; // set priority and re-insert - thread->priority = thread->next_priority = priority; + thread->priority = priority; enqueue_in_run_queue(thread); } diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 0c785a2..e2dc89c 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -167,7 +167,6 @@ Thread::Thread(const char* name, thread_id threadID, struct cpu_ent* cpu) team_next(NULL), queue_next(NULL), priority(-1), - next_priority(-1), io_priority(-1), cpu(cpu), previous_cpu(NULL), @@ -901,7 +900,6 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) // available for deinitialization thread->priority = attributes.priority == -1 ? B_NORMAL_PRIORITY : attributes.priority; - thread->next_priority = thread->priority; thread->state = B_THREAD_SUSPENDED; thread->next_state = B_THREAD_SUSPENDED; @@ -1427,7 +1425,7 @@ make_thread_unreal(int argc, char **argv) continue; if (thread->priority > B_DISPLAY_PRIORITY) { - thread->priority = thread->next_priority = B_NORMAL_PRIORITY; + thread->priority = B_NORMAL_PRIORITY; kprintf("thread %" B_PRId32 " made unreal\n", thread->id); } } @@ -1463,7 +1461,7 @@ set_thread_prio(int argc, char **argv) Thread* thread = it.Next();) { if (thread->id != id) continue; - thread->priority = thread->next_priority = prio; + thread->priority = prio; kprintf("thread %" B_PRId32 " set to priority %" B_PRId32 "\n", id, prio); found = true; break; @@ -1702,9 +1700,8 @@ _dump_thread_info(Thread *thread, bool shortInfo) kprintf("name: \"%s\"\n", thread->name); kprintf("hash_next: %p\nteam_next: %p\nq_next: %p\n", thread->hash_next, thread->team_next, thread->queue_next); - kprintf("priority: %" B_PRId32 " (next %" B_PRId32 ", " - "I/O: %" B_PRId32 ")\n", thread->priority, thread->next_priority, - thread->io_priority); + kprintf("priority: %" B_PRId32 " (I/O: %" B_PRId32 ")\n", + thread->priority, thread->io_priority); kprintf("state: %s\n", state_to_text(thread, thread->state)); kprintf("next_state: %s\n", state_to_text(thread, thread->next_state)); kprintf("cpu: %p ", thread->cpu); @@ -1919,7 +1916,7 @@ thread_exit(void) panic("thread_exit() called with interrupts disabled!\n"); // boost our priority to get this over with - thread->priority = thread->next_priority = B_URGENT_DISPLAY_PRIORITY; + thread->priority = B_URGENT_DISPLAY_PRIORITY; if (team != kernelTeam) { // Cancel previously installed alarm timer, if any. Hold the scheduler @@ -2730,7 +2727,7 @@ thread_init(kernel_args *args) gCPU[i].running_thread = thread; thread->team = team_get_kernel_team(); - thread->priority = thread->next_priority = B_IDLE_PRIORITY; + thread->priority = B_IDLE_PRIORITY; thread->state = B_THREAD_RUNNING; thread->next_state = B_THREAD_READY; sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1); @@ -3217,7 +3214,7 @@ set_thread_priority(thread_id id, int32 priority) // It's ourself, so we know we aren't in the run queue, and we can // manipulate our structure directly. oldPriority = thread->priority; - thread->priority = thread->next_priority = priority; + thread->priority = priority; } else { oldPriority = thread->priority; scheduler_set_thread_priority(thread, priority); ############################################################################ Commit: ee69e536309045ba557e9defc2436eefb06d88d3 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 19:36:49 2013 UTC kernel: Minor improvements, separate priority and yield logic ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index 99818d8..bf1a402 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -120,36 +120,21 @@ dump_run_queue(int argc, char** argv) } -static inline void -simple_yield(Thread* thread) -{ - TRACE("thread %ld yielded\n", thread->id); - sYieldedThreadPriority = max_c(sYieldedThreadPriority, thread->priority); -} - - static inline int32 simple_get_effective_priority(Thread* thread) { if (thread->priority == B_IDLE_PRIORITY) return thread->priority; + if (thread->priority >= B_FIRST_REAL_TIME_PRIORITY) + return thread->priority; scheduler_thread_data* schedulerThreadData = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); int32 effectivePriority = thread->priority; - if (effectivePriority < B_FIRST_REAL_TIME_PRIORITY) { - const int kYieldFrequency = 1 << (min_c(thread->priority, 25) / 5 + 1); - if (schedulerThreadData->forced_yield_count != 0 - && schedulerThreadData->forced_yield_count % kYieldFrequency == 0) { - TRACE("forcing thread %ld to yield\n", thread->id); - simple_yield(thread); - } + effectivePriority -= schedulerThreadData->priority_penalty; - effectivePriority -= schedulerThreadData->priority_penalty; - } - - ASSERT(schedulerThreadData->priority_penalty >= 0); + ASSERT(effectivePriority < B_FIRST_REAL_TIME_PRIORITY); ASSERT(effectivePriority >= B_LOWEST_ACTIVE_PRIORITY); return effectivePriority; @@ -157,6 +142,31 @@ simple_get_effective_priority(Thread* thread) static inline void +simple_yield(Thread* thread) +{ + TRACE("thread %ld yielded\n", thread->id); + int32 effectivePriority = simple_get_effective_priority(thread); + sYieldedThreadPriority = max_c(sYieldedThreadPriority, effectivePriority); +} + + +static inline bool +simple_should_force_yield(Thread* thread) +{ + if (thread->priority >= B_FIRST_REAL_TIME_PRIORITY) + return false; + + scheduler_thread_data* schedulerThreadData + = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + + const int kYieldFrequency = 1 << (min_c(thread->priority, 25) / 5 + 1); + + return schedulerThreadData->forced_yield_count != 0 + && schedulerThreadData->forced_yield_count % kYieldFrequency == 0; +} + + +static inline void simple_increase_penalty(Thread* thread) { if (thread->priority <= B_LOWEST_ACTIVE_PRIORITY) @@ -186,9 +196,6 @@ simple_cancel_penalty(Thread* thread) scheduler_thread_data* schedulerThreadData = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); - if (schedulerThreadData->went_sleep < 0 - || system_time() - schedulerThreadData->went_sleep <= kThreadQuantum) - return; if (schedulerThreadData->priority_penalty != 0) TRACE("cancelling thread %ld penalty\n", thread->id); schedulerThreadData->priority_penalty = 0; @@ -196,22 +203,24 @@ simple_cancel_penalty(Thread* thread) } -/*! Enqueues the thread into the run queue. - Note: thread lock must be held when entering this function -*/ static void -simple_enqueue_in_run_queue(Thread* thread) +simple_enqueue(Thread* thread, bool newOne) { thread->state = thread->next_state = B_THREAD_READY; - simple_cancel_penalty(thread); + scheduler_thread_data* schedulerThreadData + = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + + bigtime_t hasSlept = system_time() - schedulerThreadData->went_sleep; + if (newOne && hasSlept > kThreadQuantum) + simple_cancel_penalty(thread); + + if (simple_should_force_yield(thread)) + simple_yield(thread); int32 threadPriority = simple_get_effective_priority(thread); T(EnqueueThread(thread, threadPriority)); - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); - if (threadPriority <= sYieldedThreadPriority) sExpiredQueue->PushBack(thread, threadPriority); else @@ -226,7 +235,7 @@ simple_enqueue_in_run_queue(Thread* thread) thread); Thread* currentThread = thread_get_current_thread(); - if (threadPriority > currentThread->priority) { + if (newOne && threadPriority > currentThread->priority) { scheduler_thread_data* schedulerCurrentThreadData = reinterpret_cast<scheduler_thread_data*>( currentThread->scheduler_data); @@ -238,6 +247,16 @@ simple_enqueue_in_run_queue(Thread* thread) } +/*! Enqueues the thread into the run queue. + Note: thread lock must be held when entering this function +*/ +static void +simple_enqueue_in_run_queue(Thread* thread) +{ + simple_enqueue(thread, true); +} + + /*! Sets the priority of a thread. Note: thread lock must be held when entering this function */ @@ -406,8 +425,6 @@ simple_reschedule(void) schedulerOldThreadData->cpu_bound = false; if (simple_quantum_ended(oldThread, oldThread->cpu->preempted)) { - schedulerOldThreadData->went_sleep = -1; - if (schedulerOldThreadData->cpu_bound) simple_increase_penalty(oldThread); else @@ -415,11 +432,10 @@ simple_reschedule(void) if (oldThread->was_yielded) simple_yield(oldThread); - oldThread->was_yielded = false; TRACE("enqueueing thread %ld into run queue priority = %ld\n", oldThread->id, simple_get_effective_priority(oldThread)); - simple_enqueue_in_run_queue(oldThread); + simple_enqueue(oldThread, false); } else { TRACE("putting thread %ld back in run queue priority = %ld\n", oldThread->id, simple_get_effective_priority(oldThread)); @@ -441,6 +457,7 @@ simple_reschedule(void) break; } + oldThread->was_yielded = false; schedulerOldThreadData->lost_cpu = false; // select thread with the biggest priority @@ -449,6 +466,8 @@ simple_reschedule(void) panic("reschedule(): run queues are empty!\n"); sRunQueue->Remove(nextThread); + TRACE("reschedule(): next thread = %ld\n", nextThread->id); + T(ScheduleThread(nextThread, oldThread)); // notify listeners ############################################################################ Commit: 0896565a6e405d3543b15772571138d622c7fba9 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 23:18:55 2013 UTC kernel: Support sched_yield() properly sched_yield() should not yield to the threads with lower priority. ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 3e4ec90..23e10e9 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -443,7 +443,8 @@ struct Thread : TeamThreadIteratorEntry<thread_id>, KernelReferenceable, bool in_kernel; // protected by time_lock, only written by // this thread - bool was_yielded; // protected by scheduler lock + bool has_yielded; // protected by scheduler lock + bool has_fully_yielded; // protected by scheduler lock struct scheduler_thread_data* scheduler_data; // protected by scheduler lock struct user_thread* user_thread; // write-protected by fLock, only diff --git a/src/system/kernel/scheduler/scheduler_affine.cpp b/src/system/kernel/scheduler/scheduler_affine.cpp index f5b7294..fde10f0 100644 --- a/src/system/kernel/scheduler/scheduler_affine.cpp +++ b/src/system/kernel/scheduler/scheduler_affine.cpp @@ -447,7 +447,7 @@ affine_reschedule(void) nextThread->state = B_THREAD_RUNNING; nextThread->next_state = B_THREAD_READY; - oldThread->was_yielded = false; + oldThread->has_yielded = false; // track kernel time (user time is tracked in thread_at_kernel_entry()) scheduler_update_thread_times(oldThread, nextThread); diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index bf1a402..de317f1 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -324,11 +324,17 @@ reschedule_event(timer* /* unused */) } -static inline bool simple_quantum_ended(Thread* thread, bool wasPreempted) +static inline bool +simple_quantum_ended(Thread* thread, bool wasPreempted, bool hasYielded) { scheduler_thread_data* schedulerThreadData = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + if (hasYielded) { + schedulerThreadData->time_left = 0; + return true; + } + bigtime_t time_used = system_time() - schedulerThreadData->quantum_start; schedulerThreadData->time_left -= time_used; schedulerThreadData->time_left = max_c(0, schedulerThreadData->time_left); @@ -343,7 +349,8 @@ static inline bool simple_quantum_ended(Thread* thread, bool wasPreempted) } -static inline bigtime_t simple_compute_quantum(Thread* thread) +static inline bigtime_t +simple_compute_quantum(Thread* thread) { scheduler_thread_data* schedulerThreadData = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); @@ -424,13 +431,12 @@ simple_reschedule(void) if (!schedulerOldThreadData->lost_cpu) schedulerOldThreadData->cpu_bound = false; - if (simple_quantum_ended(oldThread, oldThread->cpu->preempted)) { + if (simple_quantum_ended(oldThread, oldThread->cpu->preempted, + oldThread->has_yielded)) { if (schedulerOldThreadData->cpu_bound) simple_increase_penalty(oldThread); - else - simple_cancel_penalty(oldThread); - if (oldThread->was_yielded) + if (oldThread->has_fully_yielded) simple_yield(oldThread); TRACE("enqueueing thread %ld into run queue priority = %ld\n", @@ -457,7 +463,8 @@ simple_reschedule(void) break; } - oldThread->was_yielded = false; + oldThread->has_yielded = false; + oldThread->has_fully_yielded = false; schedulerOldThreadData->lost_cpu = false; // select thread with the biggest priority diff --git a/src/system/kernel/scheduler/scheduler_simple_smp.cpp b/src/system/kernel/scheduler/scheduler_simple_smp.cpp index 092fd70..d30ce9c 100644 --- a/src/system/kernel/scheduler/scheduler_simple_smp.cpp +++ b/src/system/kernel/scheduler/scheduler_simple_smp.cpp @@ -384,7 +384,7 @@ reschedule(void) nextThread->state = B_THREAD_RUNNING; nextThread->next_state = B_THREAD_READY; - oldThread->was_yielded = false; + oldThread->has_yielded = false; // track kernel time (user time is tracked in thread_at_kernel_entry()) scheduler_update_thread_times(oldThread, nextThread); diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index e2dc89c..781720c 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -178,7 +178,8 @@ Thread::Thread(const char* name, thread_id threadID, struct cpu_ent* cpu) signal_stack_size(0), signal_stack_enabled(false), in_kernel(true), - was_yielded(false), + has_yielded(false), + has_fully_yielded(false), user_thread(NULL), fault_handler(0), page_faults_allowed(1), @@ -2443,25 +2444,15 @@ peek_next_thread_id() void thread_yield(bool force) { - if (force) { - Thread *thread = thread_get_current_thread(); - if (thread == NULL) - return; - - InterruptsSpinLocker _(gSchedulerLock); + Thread *thread = thread_get_current_thread(); + if (thread == NULL) + return; - // mark the thread as yielded, so it will not be scheduled next - thread->was_yielded = true; - scheduler_reschedule(); - } else { - Thread *thread = thread_get_current_thread(); - if (thread == NULL) - return; + InterruptsSpinLocker _(gSchedulerLock); - // Don't force the thread off the CPU, just reschedule. - InterruptsSpinLocker _(gSchedulerLock); - scheduler_reschedule(); - } + thread->has_yielded = true; + thread->has_fully_yielded = force; + scheduler_reschedule(); } @@ -3512,7 +3503,7 @@ _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags, void _user_thread_yield(void) { - thread_yield(true); + thread_yield(false); } ############################################################################ Commit: f256b4aca7aba52cafb5f405557d3470218f61a1 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 23:20:40 2013 UTC kernel: Use SimpleRunQueue as run queue type everywhere ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index de317f1..40a789a 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -85,7 +85,7 @@ scheduler_thread_data::Init() static inline void -dump_queue(RunQueue<Thread, THREAD_MAX_SET_PRIORITY>::ConstIterator& iterator) +dump_queue(SimpleRunQueue::ConstIterator& iterator) { if (!iterator.HasNext()) kprintf("Queue is empty.\n"); @@ -107,7 +107,7 @@ dump_queue(RunQueue<Thread, THREAD_MAX_SET_PRIORITY>::ConstIterator& iterator) static int dump_run_queue(int argc, char** argv) { - RunQueue<Thread, THREAD_MAX_SET_PRIORITY>::ConstIterator iterator; + SimpleRunQueue::ConstIterator iterator; kprintf("Current run queue:\n"); iterator = sRunQueue->GetConstIterator(); dump_queue(iterator); ############################################################################ Commit: 130000e068ec68a10fc632ee4ffc8a5fb563159b Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 23:37:00 2013 UTC kernel: Dump scheduler specific thread data ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_affine.cpp b/src/system/kernel/scheduler/scheduler_affine.cpp index fde10f0..471b53e 100644 --- a/src/system/kernel/scheduler/scheduler_affine.cpp +++ b/src/system/kernel/scheduler/scheduler_affine.cpp @@ -547,7 +547,8 @@ static scheduler_ops kAffineOps = { affine_on_thread_create, affine_on_thread_init, affine_on_thread_destroy, - affine_start + affine_start, + NULL }; diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index 40a789a..fe35929 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -120,6 +120,18 @@ dump_run_queue(int argc, char** argv) } +static void +simple_dump_thread_data(scheduler_thread_data* schedulerThreadData) +{ + kprintf("\tpriority_penalty:\t%" B_PRId32 "\n", + schedulerThreadData->priority_penalty); + kprintf("\tforced_yield_count:\t%" B_PRId32 "\n", + schedulerThreadData->forced_yield_count); + kprintf("\tstolen_time:\t\t%" B_PRId64 "\n", + schedulerThreadData->stolen_time); +} + + static inline int32 simple_get_effective_priority(Thread* thread) { @@ -563,7 +575,8 @@ static scheduler_ops kSimpleOps = { simple_on_thread_create, simple_on_thread_init, simple_on_thread_destroy, - simple_start + simple_start, + simple_dump_thread_data }; diff --git a/src/system/kernel/scheduler/scheduler_simple_smp.cpp b/src/system/kernel/scheduler/scheduler_simple_smp.cpp index d30ce9c..e596014 100644 --- a/src/system/kernel/scheduler/scheduler_simple_smp.cpp +++ b/src/system/kernel/scheduler/scheduler_simple_smp.cpp @@ -462,7 +462,8 @@ static scheduler_ops kSimpleSMPOps = { on_thread_create, on_thread_init, on_thread_destroy, - start + start, + NULL }; diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 781720c..66972e7 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -1786,6 +1786,10 @@ _dump_thread_info(Thread *thread, bool shortInfo) kprintf("flags: 0x%" B_PRIx32 "\n", thread->flags); kprintf("architecture dependant section:\n"); arch_thread_dump_info(&thread->arch_info); + if (gScheduler->dump_thread_data != NULL) { + kprintf("scheduler data:\n"); + gScheduler->dump_thread_data(thread->scheduler_data); + } } ############################################################################ Commit: 879ceb60d824345ff90f2f1d6a1e22a086dbe29f Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Oct 8 23:45:07 2013 UTC kernel: Remove suporfluous casts ---------------------------------------------------------------------------- diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index fe35929..54bb110 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -93,12 +93,9 @@ dump_queue(SimpleRunQueue::ConstIterator& iterator) kprintf("thread id priority penalty name\n"); while (iterator.HasNext()) { Thread* thread = iterator.Next(); - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>( - thread->scheduler_data); kprintf("%p %-7" B_PRId32 " %-8" B_PRId32 " %-8" B_PRId32 " %s\n", thread, thread->id, thread->priority, - schedulerThreadData->priority_penalty, thread->name); + thread->scheduler_data->priority_penalty, thread->name); } } } @@ -140,11 +137,8 @@ simple_get_effective_priority(Thread* thread) if (thread->priority >= B_FIRST_REAL_TIME_PRIORITY) return thread->priority; - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); - int32 effectivePriority = thread->priority; - effectivePriority -= schedulerThreadData->priority_penalty; + effectivePriority -= thread->scheduler_data->priority_penalty; ASSERT(effectivePriority < B_FIRST_REAL_TIME_PRIORITY); ASSERT(effectivePriority >= B_LOWEST_ACTIVE_PRIORITY); @@ -168,13 +162,10 @@ simple_should_force_yield(Thread* thread) if (thread->priority >= B_FIRST_REAL_TIME_PRIORITY) return false; - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); - const int kYieldFrequency = 1 << (min_c(thread->priority, 25) / 5 + 1); - return schedulerThreadData->forced_yield_count != 0 - && schedulerThreadData->forced_yield_count % kYieldFrequency == 0; + return thread->scheduler_data->forced_yield_count != 0 + && thread->scheduler_data->forced_yield_count % kYieldFrequency == 0; } @@ -188,8 +179,7 @@ simple_increase_penalty(Thread* thread) TRACE("increasing thread %ld penalty\n", thread->id); - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + scheduler_thread_data* schedulerThreadData = thread->scheduler_data; int32 oldPenalty = schedulerThreadData->priority_penalty++; ASSERT(thread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY); @@ -205,8 +195,7 @@ simple_increase_penalty(Thread* thread) static inline void simple_cancel_penalty(Thread* thread) { - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + scheduler_thread_data* schedulerThreadData = thread->scheduler_data; if (schedulerThreadData->priority_penalty != 0) TRACE("cancelling thread %ld penalty\n", thread->id); @@ -220,8 +209,7 @@ simple_enqueue(Thread* thread, bool newOne) { thread->state = thread->next_state = B_THREAD_READY; - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + scheduler_thread_data* schedulerThreadData = thread->scheduler_data; bigtime_t hasSlept = system_time() - schedulerThreadData->went_sleep; if (newOne && hasSlept > kThreadQuantum) @@ -248,11 +236,7 @@ simple_enqueue(Thread* thread, bool newOne) Thread* currentThread = thread_get_current_thread(); if (newOne && threadPriority > currentThread->priority) { - scheduler_thread_data* schedulerCurrentThreadData - = reinterpret_cast<scheduler_thread_data*>( - currentThread->scheduler_data); - - schedulerCurrentThreadData->lost_cpu = true; + currentThread->scheduler_data->lost_cpu = true; gCPU[0].invoke_scheduler = true; gCPU[0].invoke_scheduler_if_idle = false; } @@ -325,10 +309,8 @@ reschedule_event(timer* /* unused */) // This function is called as a result of the timer event set by the // scheduler. Make sure the reschedule() is invoked. Thread* thread= thread_get_current_thread(); - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); - schedulerThreadData->lost_cpu = true; + thread->scheduler_data->lost_cpu = true; thread->cpu->invoke_scheduler = true; thread->cpu->invoke_scheduler_if_idle = false; thread->cpu->preempted = 1; @@ -339,8 +321,7 @@ reschedule_event(timer* /* unused */) static inline bool simple_quantum_ended(Thread* thread, bool wasPreempted, bool hasYielded) { - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + scheduler_thread_data* schedulerThreadData = thread->scheduler_data; if (hasYielded) { schedulerThreadData->time_left = 0; @@ -364,8 +345,7 @@ simple_quantum_ended(Thread* thread, bool wasPreempted, bool hasYielded) static inline bigtime_t simple_compute_quantum(Thread* thread) { - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); + scheduler_thread_data* schedulerThreadData = thread->scheduler_data; bigtime_t quantum; if (schedulerThreadData->time_left != 0) @@ -434,8 +414,7 @@ simple_reschedule(void) TRACE("reschedule(): current thread = %ld\n", oldThread->id); oldThread->state = oldThread->next_state; - scheduler_thread_data* schedulerOldThreadData - = reinterpret_cast<scheduler_thread_data*>(oldThread->scheduler_data); + scheduler_thread_data* schedulerOldThreadData = oldThread->scheduler_data; switch (oldThread->next_state) { case B_THREAD_RUNNING: @@ -542,9 +521,7 @@ simple_on_thread_create(Thread* thread, bool idleThread) static void simple_on_thread_init(Thread* thread) { - scheduler_thread_data* schedulerThreadData - = reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data); - schedulerThreadData->Init(); + thread->scheduler_data->Init(); }