Reworked the way thread_yield() works: just setting the thread to B_LOWEST_ACTIVE_PRIORITY
for one quantum wasn't really a good idea, as this could get quite expensive for the thread (depending on the system load, it might have taken a long time until the thread was scheduled again, no matter what priority it was). Also, calling thread_yield() in a loop would have taken 100% CPU time. Now, we sort the thread into the queue as with any other thread, but we'll ignore it once. This now guarantees an actual context switch, as well as a much fairer rescheduling policy for threads calling that function. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20077 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
8c31a369ab
commit
eb117b4bfd
@ -142,6 +142,7 @@ struct thread {
|
|||||||
struct sigaction sig_action[32];
|
struct sigaction sig_action[32];
|
||||||
|
|
||||||
bool in_kernel;
|
bool in_kernel;
|
||||||
|
bool was_yielded;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
sem_id blocking;
|
sem_id blocking;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Copyright 2002, Angelo Mottola, a.mottola@libero.it.
|
* Copyright 2002, Angelo Mottola, a.mottola@libero.it.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@ -189,6 +189,13 @@ scheduler_reschedule(void)
|
|||||||
} else {
|
} else {
|
||||||
// select next thread from the run queue
|
// select next thread from the run queue
|
||||||
while (nextThread && nextThread->priority > B_IDLE_PRIORITY) {
|
while (nextThread && nextThread->priority > B_IDLE_PRIORITY) {
|
||||||
|
if (oldThread == nextThread && nextThread->was_yielded) {
|
||||||
|
// ignore threads that called thread_yield() once
|
||||||
|
nextThread->was_yielded = false;
|
||||||
|
prevThread = nextThread;
|
||||||
|
nextThread = nextThread->queue_next;
|
||||||
|
}
|
||||||
|
|
||||||
// always extract real time threads
|
// always extract real time threads
|
||||||
if (nextThread->priority >= B_FIRST_REAL_TIME_PRIORITY)
|
if (nextThread->priority >= B_FIRST_REAL_TIME_PRIORITY)
|
||||||
break;
|
break;
|
||||||
@ -222,6 +229,7 @@ scheduler_reschedule(void)
|
|||||||
|
|
||||||
nextThread->state = B_THREAD_RUNNING;
|
nextThread->state = B_THREAD_RUNNING;
|
||||||
nextThread->next_state = B_THREAD_READY;
|
nextThread->next_state = B_THREAD_READY;
|
||||||
|
oldThread->was_yielded = false;
|
||||||
|
|
||||||
// track kernel time (user time is tracked in thread_at_kernel_entry())
|
// track kernel time (user time is tracked in thread_at_kernel_entry())
|
||||||
bigtime_t now = system_time();
|
bigtime_t now = system_time();
|
||||||
|
@ -214,6 +214,7 @@ create_thread_struct(const char *name, thread_id threadID)
|
|||||||
thread->sig_block_mask = 0;
|
thread->sig_block_mask = 0;
|
||||||
memset(thread->sig_action, 0, 32 * sizeof(struct sigaction));
|
memset(thread->sig_action, 0, 32 * sizeof(struct sigaction));
|
||||||
thread->in_kernel = true;
|
thread->in_kernel = true;
|
||||||
|
thread->was_yielded = false;
|
||||||
thread->user_time = 0;
|
thread->user_time = 0;
|
||||||
thread->kernel_time = 0;
|
thread->kernel_time = 0;
|
||||||
thread->last_time = 0;
|
thread->last_time = 0;
|
||||||
@ -915,13 +916,13 @@ thread_exit(void)
|
|||||||
struct thread_debug_info debugInfo;
|
struct thread_debug_info debugInfo;
|
||||||
team_id teamID = team->id;
|
team_id teamID = team->id;
|
||||||
|
|
||||||
if (!are_interrupts_enabled())
|
|
||||||
dprintf("thread_exit() called with interrupts disabled!\n");
|
|
||||||
|
|
||||||
TRACE(("thread 0x%lx exiting %s w/return code 0x%x\n", thread->id,
|
TRACE(("thread 0x%lx exiting %s w/return code 0x%x\n", thread->id,
|
||||||
thread->exit.reason == THREAD_RETURN_INTERRUPTED ? "due to signal" : "normally",
|
thread->exit.reason == THREAD_RETURN_INTERRUPTED ? "due to signal" : "normally",
|
||||||
(int)thread->exit.status));
|
(int)thread->exit.status));
|
||||||
|
|
||||||
|
if (!are_interrupts_enabled())
|
||||||
|
panic("thread_exit() called with interrupts disabled!\n");
|
||||||
|
|
||||||
// boost our priority to get this over with
|
// boost our priority to get this over with
|
||||||
thread->priority = thread->next_priority = B_URGENT_DISPLAY_PRIORITY;
|
thread->priority = thread->next_priority = B_URGENT_DISPLAY_PRIORITY;
|
||||||
|
|
||||||
@ -1298,8 +1299,8 @@ thread_yield(void)
|
|||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
// just add the thread at the end of the run queue
|
// mark the thread as yielded, so it will not be scheduled next
|
||||||
thread->next_priority = B_LOWEST_ACTIVE_PRIORITY;
|
thread->was_yielded = true;
|
||||||
scheduler_reschedule();
|
scheduler_reschedule();
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
|
Loading…
Reference in New Issue
Block a user