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:
Rene Gollent 2009-03-26 00:58:20 +00:00
parent 4ecbee4f94
commit 0296b82ae6
5 changed files with 104 additions and 5 deletions

View File

@ -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" {

View File

@ -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;

View File

@ -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
};

View File

@ -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
};

View File

@ -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();