Add several extra scheduler hook functions to allow the scheduler(s) to maintain private housekeeping data on the thread structs. These hooks are called on thread creation/destruction and when prepping a thread for use. Review welcome.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29721 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4ecbee4f94
commit
0296b82ae6
@ -18,7 +18,18 @@ struct scheduler_ops {
|
||||
void (*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 -
|
||||
// initialization of per-thread housekeeping data structures should
|
||||
// be done here
|
||||
void (*on_thread_create)(struct thread* thread);
|
||||
// called when a thread structure is initialized and made ready for
|
||||
// use - should be used to reset the housekeeping data structures
|
||||
// if needed
|
||||
void (*on_thread_init)(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 (*on_thread_destroy)(struct thread* thread);
|
||||
|
||||
void (*start)(void);
|
||||
};
|
||||
|
||||
@ -30,7 +41,12 @@ extern struct scheduler_ops* gScheduler;
|
||||
gScheduler->set_thread_priority(thread, priority)
|
||||
#define scheduler_reschedule() gScheduler->reschedule()
|
||||
#define scheduler_start() gScheduler->start()
|
||||
|
||||
#define scheduler_on_thread_create(thread) \
|
||||
gScheduler->on_thread_create(thread)
|
||||
#define scheduler_on_thread_init(thread) \
|
||||
gScheduler->on_thread_init(thread)
|
||||
#define scheduler_on_thread_destroy(thread) \
|
||||
gScheduler->on_thread_destroy(thread)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -158,6 +158,10 @@ struct free_user_thread {
|
||||
struct user_thread* thread;
|
||||
};
|
||||
|
||||
struct scheduler_thread_data {
|
||||
// empty, left up to the individual schedulers to subclass / define
|
||||
};
|
||||
|
||||
struct team {
|
||||
struct team *next; // next in hash
|
||||
struct team *siblings_next;
|
||||
@ -248,6 +252,7 @@ struct thread {
|
||||
|
||||
bool in_kernel;
|
||||
bool was_yielded;
|
||||
struct scheduler_thread_data* scheduler_data;
|
||||
|
||||
struct user_thread* user_thread;
|
||||
|
||||
|
@ -40,6 +40,23 @@ static struct thread* sRunQueue[B_MAX_CPU_COUNT];
|
||||
static struct thread* sIdleThreads;
|
||||
static cpu_mask_t sIdleCPUs = 0;
|
||||
|
||||
struct affine_scheduler_data : public scheduler_thread_data
|
||||
{
|
||||
affine_scheduler_data(void)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
memset(fLastThreadQuantums, 0, sizeof(fLastThreadQuantums));
|
||||
fLastQuantumSlot = 0;
|
||||
}
|
||||
|
||||
int32 fLastThreadQuantums[5];
|
||||
int16 fLastQuantumSlot;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
_rand(void)
|
||||
@ -441,6 +458,29 @@ affine_reschedule(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
affine_on_thread_create(struct thread* thread)
|
||||
{
|
||||
thread->scheduler_data = new(std::nothrow) affine_scheduler_data();
|
||||
if (thread->scheduler_data == NULL)
|
||||
panic("affine_scheduler: Unable to allocate scheduling data structure for thread %ld\n", thread->id);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
affine_on_thread_init(struct thread* thread)
|
||||
{
|
||||
((affine_scheduler_data *)(thread->scheduler_data))->init();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
affine_on_thread_destroy(struct thread* thread)
|
||||
{
|
||||
delete thread->scheduler_data;
|
||||
}
|
||||
|
||||
|
||||
/*! This starts the scheduler. Must be run under the context of
|
||||
the initial idle thread.
|
||||
*/
|
||||
@ -461,6 +501,9 @@ static scheduler_ops kAffineOps = {
|
||||
affine_enqueue_in_run_queue,
|
||||
affine_reschedule,
|
||||
affine_set_thread_priority,
|
||||
affine_on_thread_create,
|
||||
affine_on_thread_init,
|
||||
affine_on_thread_destroy,
|
||||
affine_start
|
||||
};
|
||||
|
||||
|
@ -380,6 +380,27 @@ simple_reschedule(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
simple_on_thread_create(struct thread* thread)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
simple_on_thread_init(struct thread* thread)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
simple_on_thread_destroy(struct thread* thread)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
/*! This starts the scheduler. Must be run under the context of
|
||||
the initial idle thread.
|
||||
*/
|
||||
@ -400,6 +421,9 @@ static scheduler_ops kSimpleOps = {
|
||||
simple_enqueue_in_run_queue,
|
||||
simple_reschedule,
|
||||
simple_set_thread_priority,
|
||||
simple_on_thread_create,
|
||||
simple_on_thread_init,
|
||||
simple_on_thread_destroy,
|
||||
simple_start
|
||||
};
|
||||
|
||||
|
@ -195,6 +195,7 @@ create_thread_struct(struct thread *inthread, const char *name,
|
||||
struct thread *thread;
|
||||
cpu_status state;
|
||||
char temp[64];
|
||||
bool recycled = false;
|
||||
|
||||
if (inthread == NULL) {
|
||||
// try to recycle one from the dead queue first
|
||||
@ -209,10 +210,15 @@ create_thread_struct(struct thread *inthread, const char *name,
|
||||
thread = (struct thread *)malloc(sizeof(struct thread));
|
||||
if (thread == NULL)
|
||||
return NULL;
|
||||
} else {
|
||||
recycled = true;
|
||||
}
|
||||
} else {
|
||||
thread = inthread;
|
||||
}
|
||||
|
||||
if (!recycled)
|
||||
scheduler_on_thread_create(thread);
|
||||
|
||||
if (name != NULL)
|
||||
strlcpy(thread->name, name, B_OS_NAME_LENGTH);
|
||||
@ -253,7 +259,7 @@ create_thread_struct(struct thread *inthread, const char *name,
|
||||
thread->select_infos = NULL;
|
||||
thread->post_interrupt_callback = NULL;
|
||||
thread->post_interrupt_data = NULL;
|
||||
|
||||
|
||||
sprintf(temp, "thread_%ld_retcode_sem", thread->id);
|
||||
thread->exit.sem = create_sem(0, temp);
|
||||
if (thread->exit.sem < B_OK)
|
||||
@ -271,7 +277,7 @@ create_thread_struct(struct thread *inthread, const char *name,
|
||||
|
||||
if (arch_thread_init_thread_struct(thread) < B_OK)
|
||||
goto err4;
|
||||
|
||||
|
||||
return thread;
|
||||
|
||||
err4:
|
||||
@ -282,8 +288,10 @@ err2:
|
||||
delete_sem(thread->exit.sem);
|
||||
err1:
|
||||
// ToDo: put them in the dead queue instead?
|
||||
if (inthread == NULL)
|
||||
if (inthread == NULL) {
|
||||
free(thread);
|
||||
scheduler_on_thread_destroy(thread);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -295,6 +303,8 @@ delete_thread_struct(struct thread *thread)
|
||||
delete_sem(thread->msg.write_sem);
|
||||
delete_sem(thread->msg.read_sem);
|
||||
|
||||
scheduler_on_thread_destroy(thread);
|
||||
|
||||
// ToDo: put them in the dead queue instead?
|
||||
free(thread);
|
||||
}
|
||||
@ -446,6 +456,7 @@ create_thread(thread_creation_attributes& attributes, bool kernel)
|
||||
// insert into global list
|
||||
hash_insert(sThreadHash, thread);
|
||||
sUsedThreads++;
|
||||
scheduler_on_thread_init(thread);
|
||||
RELEASE_THREAD_LOCK();
|
||||
|
||||
GRAB_TEAM_LOCK();
|
||||
|
Loading…
Reference in New Issue
Block a user