bonefish+axeld:
* Implemented a tiny bit more sophisticated version of estimate_max_scheduling_latency() that uses a syscall that lets the scheduler decide. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36170 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
* Copyright 2008-2010, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2005, Axel Dörfler, [email protected].
|
* Copyright 2005-2010, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef KERNEL_SCHEDULER_H
|
#ifndef KERNEL_SCHEDULER_H
|
||||||
@@ -22,17 +22,19 @@ struct scheduler_ops {
|
|||||||
void (*enqueue_in_run_queue)(struct thread* thread);
|
void (*enqueue_in_run_queue)(struct thread* thread);
|
||||||
void (*reschedule)(void);
|
void (*reschedule)(void);
|
||||||
void (*set_thread_priority)(struct thread* thread, int32 priority);
|
void (*set_thread_priority)(struct thread* thread, int32 priority);
|
||||||
// called when the thread structure is first created -
|
bigtime_t (*estimate_max_scheduling_latency)(struct thread* thread);
|
||||||
// initialization of per-thread housekeeping data structures should
|
|
||||||
// be done here
|
|
||||||
void (*on_thread_create)(struct thread* thread);
|
void (*on_thread_create)(struct thread* thread);
|
||||||
// called when a thread structure is initialized and made ready for
|
// called when the thread structure is first created -
|
||||||
// use - should be used to reset the housekeeping data structures
|
// initialization of per-thread housekeeping data structures should
|
||||||
// if needed
|
// be done here
|
||||||
void (*on_thread_init)(struct thread* thread);
|
void (*on_thread_init)(struct thread* thread);
|
||||||
// called when a thread structure is freed - freeing up any allocated
|
// called when a thread structure is initialized and made ready for
|
||||||
// mem on the scheduler's part should be done here
|
// use - should be used to reset the housekeeping data structures
|
||||||
|
// if needed
|
||||||
void (*on_thread_destroy)(struct thread* thread);
|
void (*on_thread_destroy)(struct thread* thread);
|
||||||
|
// called when a thread structure is freed - freeing up any allocated
|
||||||
|
// mem on the scheduler's part should be done here
|
||||||
|
|
||||||
void (*start)(void);
|
void (*start)(void);
|
||||||
};
|
};
|
||||||
@@ -61,6 +63,7 @@ void scheduler_remove_listener(struct SchedulerListener* listener);
|
|||||||
|
|
||||||
void scheduler_init(void);
|
void scheduler_init(void);
|
||||||
|
|
||||||
|
bigtime_t _user_estimate_max_scheduling_latency(thread_id thread);
|
||||||
status_t _user_analyze_scheduling(bigtime_t from, bigtime_t until, void* buffer,
|
status_t _user_analyze_scheduling(bigtime_t from, bigtime_t until, void* buffer,
|
||||||
size_t size, struct scheduling_analysis* analysis);
|
size_t size, struct scheduling_analysis* analysis);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2009, Haiku Inc. All rights reserved.
|
* Copyright 2004-2010, Haiku Inc. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _SYSTEM_SYSCALLS_H
|
#ifndef _SYSTEM_SYSCALLS_H
|
||||||
@@ -177,6 +177,8 @@ extern status_t _kern_unblock_thread(thread_id thread, status_t status);
|
|||||||
extern status_t _kern_unblock_threads(thread_id* threads, uint32 count,
|
extern status_t _kern_unblock_threads(thread_id* threads, uint32 count,
|
||||||
status_t status);
|
status_t status);
|
||||||
|
|
||||||
|
extern bigtime_t _kern_estimate_max_scheduling_latency(thread_id thread);
|
||||||
|
|
||||||
// user/group functions
|
// user/group functions
|
||||||
extern gid_t _kern_getgid(bool effective);
|
extern gid_t _kern_getgid(bool effective);
|
||||||
extern uid_t _kern_getuid(bool effective);
|
extern uid_t _kern_getuid(bool effective);
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
* Copyright 2008-2010, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2010, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <kscheduler.h>
|
#include <kscheduler.h>
|
||||||
#include <listeners.h>
|
#include <listeners.h>
|
||||||
#include <smp.h>
|
#include <smp.h>
|
||||||
@@ -68,3 +70,22 @@ scheduler_init(void)
|
|||||||
" <thread> - ID of the thread.\n", 0);
|
" <thread> - ID of the thread.\n", 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Syscalls
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
_user_estimate_max_scheduling_latency(thread_id id)
|
||||||
|
{
|
||||||
|
syscall_64_bit_return_value();
|
||||||
|
|
||||||
|
InterruptsSpinLocker locker(gThreadSpinlock);
|
||||||
|
|
||||||
|
struct thread* thread = id < 0
|
||||||
|
? thread_get_current_thread() : thread_get_thread_struct_locked(id);
|
||||||
|
if (thread == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return gScheduler->estimate_max_scheduling_latency(thread);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Rene Gollent, [email protected].
|
* Copyright 2009, Rene Gollent, [email protected].
|
||||||
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
* Copyright 2008-2010, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2002-2007, Axel Dörfler, [email protected].
|
* Copyright 2002-2010, Axel Dörfler, [email protected].
|
||||||
* Copyright 2002, Angelo Mottola, [email protected].
|
* Copyright 2002, Angelo Mottola, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -321,6 +321,24 @@ affine_set_thread_priority(struct thread *thread, int32 priority)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bigtime_t
|
||||||
|
affine_estimate_max_scheduling_latency(struct thread* thread)
|
||||||
|
{
|
||||||
|
// TODO: This is probably meant to be called periodically to return the
|
||||||
|
// current estimate depending on the system usage; we return fixed estimates
|
||||||
|
// per thread priority, though.
|
||||||
|
|
||||||
|
if (thread->priority >= B_REAL_TIME_DISPLAY_PRIORITY)
|
||||||
|
return kMinThreadQuantum / 4;
|
||||||
|
if (thread->priority >= B_DISPLAY_PRIORITY)
|
||||||
|
return kMinThreadQuantum;
|
||||||
|
if (thread->priority < B_NORMAL_PRIORITY)
|
||||||
|
return 2 * kMaxThreadQuantum;
|
||||||
|
|
||||||
|
return 2 * kMinThreadQuantum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
context_switch(struct thread *fromThread, struct thread *toThread)
|
context_switch(struct thread *fromThread, struct thread *toThread)
|
||||||
{
|
{
|
||||||
@@ -556,6 +574,7 @@ static scheduler_ops kAffineOps = {
|
|||||||
affine_enqueue_in_run_queue,
|
affine_enqueue_in_run_queue,
|
||||||
affine_reschedule,
|
affine_reschedule,
|
||||||
affine_set_thread_priority,
|
affine_set_thread_priority,
|
||||||
|
affine_estimate_max_scheduling_latency,
|
||||||
affine_on_thread_create,
|
affine_on_thread_create,
|
||||||
affine_on_thread_init,
|
affine_on_thread_init,
|
||||||
affine_on_thread_destroy,
|
affine_on_thread_destroy,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, [email protected].
|
* Copyright 2008-2010, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
* Copyright 2002-2010, Axel Dörfler, [email protected].
|
||||||
* Copyright 2002, Angelo Mottola, [email protected].
|
* Copyright 2002, Angelo Mottola, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -36,6 +36,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
const bigtime_t kThreadQuantum = 3000;
|
||||||
|
|
||||||
|
|
||||||
// The run queue. Holds the threads ready to run ordered by priority.
|
// The run queue. Holds the threads ready to run ordered by priority.
|
||||||
static struct thread *sRunQueue = NULL;
|
static struct thread *sRunQueue = NULL;
|
||||||
|
|
||||||
@@ -160,6 +163,22 @@ simple_set_thread_priority(struct thread *thread, int32 priority)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bigtime_t
|
||||||
|
simple_estimate_max_scheduling_latency(struct thread* thread)
|
||||||
|
{
|
||||||
|
// TODO: This is probably meant to be called periodically to return the
|
||||||
|
// current estimate depending on the system usage; we return fixed estimates
|
||||||
|
// per thread priority, though.
|
||||||
|
|
||||||
|
if (thread->priority >= B_REAL_TIME_DISPLAY_PRIORITY)
|
||||||
|
return kThreadQuantum / 4;
|
||||||
|
if (thread->priority >= B_DISPLAY_PRIORITY)
|
||||||
|
return kThreadQuantum;
|
||||||
|
|
||||||
|
return 2 * kThreadQuantum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
context_switch(struct thread *fromThread, struct thread *toThread)
|
context_switch(struct thread *fromThread, struct thread *toThread)
|
||||||
{
|
{
|
||||||
@@ -322,8 +341,8 @@ simple_reschedule(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nextThread != oldThread || oldThread->cpu->preempted) {
|
if (nextThread != oldThread || oldThread->cpu->preempted) {
|
||||||
bigtime_t quantum = 3000; // ToDo: calculate quantum!
|
bigtime_t quantum = kThreadQuantum; // TODO: calculate quantum?
|
||||||
timer *quantumTimer = &oldThread->cpu->quantum_timer;
|
timer* quantumTimer = &oldThread->cpu->quantum_timer;
|
||||||
|
|
||||||
if (!oldThread->cpu->preempted)
|
if (!oldThread->cpu->preempted)
|
||||||
cancel_timer(quantumTimer);
|
cancel_timer(quantumTimer);
|
||||||
@@ -377,6 +396,7 @@ static scheduler_ops kSimpleOps = {
|
|||||||
simple_enqueue_in_run_queue,
|
simple_enqueue_in_run_queue,
|
||||||
simple_reschedule,
|
simple_reschedule,
|
||||||
simple_set_thread_priority,
|
simple_set_thread_priority,
|
||||||
|
simple_estimate_max_scheduling_latency,
|
||||||
simple_on_thread_create,
|
simple_on_thread_create,
|
||||||
simple_on_thread_init,
|
simple_on_thread_init,
|
||||||
simple_on_thread_destroy,
|
simple_on_thread_destroy,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
* Copyright 2008-2010, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
* Copyright 2002-2010, Axel Dörfler, [email protected].
|
||||||
* Copyright 2002, Angelo Mottola, [email protected].
|
* Copyright 2002, Angelo Mottola, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -37,6 +37,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
const bigtime_t kThreadQuantum = 3000;
|
||||||
|
|
||||||
|
|
||||||
// The run queue. Holds the threads ready to run ordered by priority.
|
// The run queue. Holds the threads ready to run ordered by priority.
|
||||||
static struct thread *sRunQueue = NULL;
|
static struct thread *sRunQueue = NULL;
|
||||||
static int32 sCPUCount = 1;
|
static int32 sCPUCount = 1;
|
||||||
@@ -225,6 +228,22 @@ set_thread_priority(struct thread *thread, int32 priority)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bigtime_t
|
||||||
|
estimate_max_scheduling_latency(struct thread* thread)
|
||||||
|
{
|
||||||
|
// TODO: This is probably meant to be called periodically to return the
|
||||||
|
// current estimate depending on the system usage; we return fixed estimates
|
||||||
|
// per thread priority, though.
|
||||||
|
|
||||||
|
if (thread->priority >= B_REAL_TIME_DISPLAY_PRIORITY)
|
||||||
|
return kThreadQuantum / 4;
|
||||||
|
if (thread->priority >= B_DISPLAY_PRIORITY)
|
||||||
|
return kThreadQuantum;
|
||||||
|
|
||||||
|
return 2 * kThreadQuantum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
context_switch(struct thread *fromThread, struct thread *toThread)
|
context_switch(struct thread *fromThread, struct thread *toThread)
|
||||||
{
|
{
|
||||||
@@ -367,7 +386,7 @@ reschedule(void)
|
|||||||
if (nextThread->cpu
|
if (nextThread->cpu
|
||||||
&& nextThread->cpu->cpu_num != oldThread->cpu->cpu_num) {
|
&& nextThread->cpu->cpu_num != oldThread->cpu->cpu_num) {
|
||||||
panic("thread in run queue that's still running on another CPU!\n");
|
panic("thread in run queue that's still running on another CPU!\n");
|
||||||
// ToDo: remove this check completely when we're sure that this
|
// TODO: remove this check completely when we're sure that this
|
||||||
// cannot happen anymore.
|
// cannot happen anymore.
|
||||||
prevThread = nextThread;
|
prevThread = nextThread;
|
||||||
nextThread = nextThread->queue_next;
|
nextThread = nextThread->queue_next;
|
||||||
@@ -415,8 +434,8 @@ reschedule(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nextThread != oldThread || oldThread->cpu->preempted) {
|
if (nextThread != oldThread || oldThread->cpu->preempted) {
|
||||||
bigtime_t quantum = 3000; // ToDo: calculate quantum!
|
bigtime_t quantum = kThreadQuantum; // TODO: calculate quantum?
|
||||||
timer *quantumTimer = &oldThread->cpu->quantum_timer;
|
timer* quantumTimer = &oldThread->cpu->quantum_timer;
|
||||||
|
|
||||||
if (!oldThread->cpu->preempted)
|
if (!oldThread->cpu->preempted)
|
||||||
cancel_timer(quantumTimer);
|
cancel_timer(quantumTimer);
|
||||||
@@ -470,6 +489,7 @@ static scheduler_ops kSimpleSMPOps = {
|
|||||||
enqueue_in_run_queue,
|
enqueue_in_run_queue,
|
||||||
reschedule,
|
reschedule,
|
||||||
set_thread_priority,
|
set_thread_priority,
|
||||||
|
estimate_max_scheduling_latency,
|
||||||
on_thread_create,
|
on_thread_create,
|
||||||
on_thread_init,
|
on_thread_init,
|
||||||
on_thread_destroy,
|
on_thread_destroy,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2008, Haiku. All rights reserved.
|
* Copyright 2004-2010, Haiku. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
uint32 what;
|
uint32 what;
|
||||||
@@ -39,6 +41,8 @@ suggest_thread_priority(uint32 what, int32 period, bigtime_t jitter,
|
|||||||
int32 priority = what == B_DEFAULT_MEDIA_PRIORITY ? 0x0a : 0;
|
int32 priority = what == B_DEFAULT_MEDIA_PRIORITY ? 0x0a : 0;
|
||||||
// default priority
|
// default priority
|
||||||
|
|
||||||
|
// TODO: this needs kernel support, and is a pretty simplistic solution
|
||||||
|
|
||||||
for (i = 0; sWhatPriorityArray[i].what != (uint32)-1; i ++) {
|
for (i = 0; sWhatPriorityArray[i].what != (uint32)-1; i ++) {
|
||||||
if ((what & sWhatPriorityArray[i].what) != 0) {
|
if ((what & sWhatPriorityArray[i].what) != 0) {
|
||||||
priority = sWhatPriorityArray[i].priority;
|
priority = sWhatPriorityArray[i].priority;
|
||||||
@@ -53,9 +57,6 @@ suggest_thread_priority(uint32 what, int32 period, bigtime_t jitter,
|
|||||||
bigtime_t
|
bigtime_t
|
||||||
estimate_max_scheduling_latency(thread_id thread)
|
estimate_max_scheduling_latency(thread_id thread)
|
||||||
{
|
{
|
||||||
if (thread == -1)
|
return _kern_estimate_max_scheduling_latency(thread);
|
||||||
thread = find_thread(NULL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user