Enabled the single ordered queue scheduler and made some little fixes

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1804 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
lillo
2002-10-31 13:20:00 +00:00
parent 6ac523ea9b
commit 5e7d6a17a0
7 changed files with 42 additions and 193 deletions
-9
View File
@@ -13,9 +13,6 @@ extern "C" {
#include <arch/thread.h>
#include <signal.h>
// Uncomment the line below to compile the single-queue scheduler
//#define NEW_SCHEDULER
void resched(void);
void start_scheduler(void);
@@ -27,13 +24,7 @@ void thread_enqueue(struct thread *t, struct thread_queue *q);
struct thread *thread_lookat_queue(struct thread_queue *q);
struct thread *thread_dequeue(struct thread_queue *q);
struct thread *thread_dequeue_id(struct thread_queue *q, thread_id thr_id);
#ifndef NEW_SCHEDULER
struct thread *thread_lookat_run_q(int priority);
#endif /* not NEW_SCHEDULER */
void thread_enqueue_run_q(struct thread *t);
#ifndef NEW_SCHEDULER
struct thread *thread_dequeue_run_q(int priority);
#endif /* not NEW_SCHEDULER */
void thread_atkernel_entry(void);
// called when the thread enters the kernel on behalf of the thread
void thread_atkernel_exit(void);
+6 -1
View File
@@ -102,13 +102,18 @@ int main(int argc, char **argv)
resume_thread(t[1]);
resume_thread(t[2]);
printf("Snoozing...\n");
snooze(100000);
printf("Waiting for threads...");
sys_wait_on_thread(t[0], NULL);
printf("1, ");
sys_wait_on_thread(t[1], NULL);
printf("2, ");
sys_wait_on_thread(t[2], NULL);
printf("3.\nDone. Spawning commthread...\n");
t[0] = spawn_thread(communication_test, "commthread", B_NORMAL_PRIORITY, (void *)5);
printf("Spawned. Starting communication...\n");
resume_thread(t[0]);
for (i=0; i<5; i++) {
+26 -85
View File
@@ -18,17 +18,33 @@
#include <smp.h>
#include <cpu.h>
#include <khash.h>
#ifdef NEW_SCHEDULER
#include <Errors.h>
#include <kerrors.h>
#endif /* NEW_SCHEDULER */
static int _rand(void);
#ifdef NEW_SCHEDULER
// The run queue. Holds the threads ready to run ordered by priority.
static struct thread_queue run_q = { NULL, NULL };
static int dump_run_q(int argc, char **argv);
static int
dump_run_q(int argc, char **argv)
{
struct thread *t;
t = run_q.head;
if (!t)
dprintf("Run queue is empty!\n");
else {
while (t) {
dprintf("Thread id: %ld - priority: %d\n", t->id, t->priority);
t = t->q_next;
}
}
return 0;
}
void
@@ -113,7 +129,6 @@ thread_set_priority(thread_id id, int32 priority)
}
#endif /* NEW_SCHEDULER */
static int
_rand(void)
{
@@ -151,6 +166,8 @@ start_scheduler(void)
RELEASE_THREAD_LOCK();
restore_interrupts(state);
add_debugger_command("run_q", &dump_run_q, "list threads in run queue");
}
@@ -186,24 +203,12 @@ reschedule_event(timer *unused)
void
resched(void)
{
#ifndef NEW_SCHEDULER
struct thread *next_thread = NULL;
int last_thread_pri = -1;
#else /* NEW_SCHEDULER */
struct thread *next_thread, *prev_thread = NULL;
#endif /* NEW_SCHEDULER */
struct thread *next_thread, *prev_thread;
struct thread *old_thread = thread_get_current_thread();
#ifndef NEW_SCHEDULER
int i;
#endif /* not NEW_SCHEDULER */
bigtime_t quantum;
timer *quantum_timer;
#ifndef NEW_SCHEDULER
// dprintf("top of thread_resched: cpu %d, cur_thread = 0x%x\n", smp_get_current_cpu(), thread_get_current_thread());
#else /* NEW_SCHEDULER */
// dprintf("resched(): cpu %d, cur_thread = 0x%x\n", smp_get_current_cpu(), thread_get_current_thread());
#endif /* NEW_SCHEDULER */
switch(old_thread->next_state) {
case B_THREAD_RUNNING:
@@ -212,11 +217,7 @@ resched(void)
thread_enqueue_run_q(old_thread);
break;
case B_THREAD_SUSPENDED:
#ifndef NEW_SCHEDULER
dprintf("suspending thread 0x%lx\n", old_thread->id);
#else /* NEW_SCHEDULER */
dprintf("resched(): suspending thread 0x%x\n", old_thread->id);
#endif /* NEW_SCHEDULER */
dprintf("resched(): suspending thread 0x%lx\n", old_thread->id);
break;
case THREAD_STATE_FREE_ON_RESCHED:
// This will hopefully be eliminated once the slab
@@ -229,40 +230,9 @@ resched(void)
}
old_thread->state = old_thread->next_state;
#ifndef NEW_SCHEDULER
// search the real-time queue
for(i = B_MAX_PRIORITY; i >= B_FIRST_REAL_TIME_PRIORITY; i-=2) {
next_thread = thread_dequeue_run_q(i);
if(next_thread)
goto found_thread;
}
// search the regular queue
for(i = B_FIRST_REAL_TIME_PRIORITY - 1; i >= B_LOWEST_ACTIVE_PRIORITY; i-=2) {
next_thread = thread_lookat_run_q(i);
if(next_thread != NULL) {
// skip it sometimes
if(_rand() > 0x3000) {
next_thread = thread_dequeue_run_q(i);
goto found_thread;
}
last_thread_pri = i;
next_thread = NULL;
}
}
if(next_thread == NULL) {
if(last_thread_pri != -1) {
next_thread = thread_dequeue_run_q(last_thread_pri);
if(next_thread == NULL)
panic("next_thread == NULL! last_thread_pri = %d\n", last_thread_pri);
} else {
next_thread = thread_dequeue_run_q(B_IDLE_PRIORITY);
if(next_thread == NULL)
panic("next_thread == NULL! no idle priorities!\n");
}
#else /* NEW_SCHEDULER */
// select next thread from the run queue
next_thread = run_q.head;
prev_thread = NULL;
while ((next_thread) && (next_thread->priority > B_IDLE_PRIORITY)) {
// always extract real time threads
if (next_thread->priority >= B_FIRST_REAL_TIME_PRIORITY)
@@ -275,12 +245,8 @@ resched(void)
break;
prev_thread = next_thread;
next_thread = next_thread->q_next;
#endif /* NEW_SCHEDULER */
}
#ifndef NEW_SCHEDULER
found_thread:
#else /* NEW_SCHEDULER */
if (!next_thread)
panic("resched(): run queue is empty!\n");
@@ -290,7 +256,6 @@ found_thread:
else
run_q.head = next_thread->q_next;
#endif /* NEW_SCHEDULER */
next_thread->state = B_THREAD_RUNNING;
next_thread->next_state = B_THREAD_READY;
@@ -305,29 +270,5 @@ found_thread:
if (next_thread != old_thread)
context_switch(old_thread, next_thread);
}
#ifndef NEW_SCHEDULER
#if 0
// XXX should only reset the quantum timer if we are switching to a new thread,
// or we got here as a result of a quantum expire.
// XXX calculate quantum
quantum = 10000;
// get the quantum timer for this cpu
quantum_timer = &old_thread->cpu->info.quantum_timer;
if(!old_thread->cpu->info.preempted) {
_local_timer_cancel_event(old_thread->cpu->info.cpu_num, quantum_timer);
}
old_thread->cpu->info.preempted = 0;
add_timer(quantum_timer, &reschedule_event, quantum, B_ONE_SHOT_RELATIVE_TIMER);
if(next_thread != old_thread) {
// dprintf("thread_resched: cpu %d switching from thread %d to %d\n",
// smp_get_current_cpu(), old_thread->id, next_thread->id);
context_switch(old_thread, next_thread);
}
#endif
#endif /* not NEW_SCHEDULER */
}
+4 -4
View File
@@ -342,7 +342,7 @@ sem_timeout(timer *data)
wakeup_queue.head = wakeup_queue.tail = NULL;
remove_thread_from_sem(t, &gSems[slot], &wakeup_queue, B_TIMED_OUT);
RELEASE_SEM_LOCK(gSems[slot]);
GRAB_THREAD_LOCK();
@@ -766,10 +766,10 @@ sem_interrupt_thread(struct thread *t)
if (t->state != B_THREAD_WAITING || t->sem_blocking < 0)
return EINVAL;
if ((t->sem_flags & B_CAN_INTERRUPT) == 0)
if (!(t->sem_flags & B_CAN_INTERRUPT))
return ERR_SEM_NOT_INTERRUPTABLE;
t->next_state = B_THREAD_READY;
// t->next_state = B_THREAD_READY;
slot = t->sem_blocking % MAX_SEMS;
@@ -808,7 +808,7 @@ remove_thread_from_sem(struct thread *t, struct sem_entry *sem, struct thread_qu
if (t != t1)
return ERR_NOT_FOUND;
sem->count += t->sem_acquire_count;
t->state = B_THREAD_READY;
t->state = t->next_state = B_THREAD_READY;
t->sem_errcode = sem_errcode;
thread_enqueue(t, queue);
+2 -5
View File
@@ -153,8 +153,7 @@ send_signal_etc(pid_t tid, uint sig, uint32 flags)
break;
case SIGCONT:
// Wake up thread if it was suspended
if ((t->state == B_THREAD_READY) ||
(t->state == B_THREAD_SUSPENDED)) {
if (t->state == B_THREAD_SUSPENDED) {
t->state = t->next_state = B_THREAD_READY;
thread_enqueue_run_q(t);
}
@@ -252,9 +251,7 @@ sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
static int32
alarm_event(timer *t)
{
int tid = *((int *)((void *)t + sizeof(timer)));
send_signal_etc(tid, SIGALRM, B_DO_NOT_RESCHEDULE);
send_signal_etc(thread_get_current_thread()->id, SIGALRM, B_DO_NOT_RESCHEDULE);
return B_INVOKE_SCHEDULER;
}
+3 -88
View File
@@ -62,21 +62,13 @@ static unsigned int num_death_stacks;
static unsigned int volatile death_stack_bitmap;
static sem_id death_stack_sem;
#ifndef NEW_SCHEDULER
// thread queues
// Thread priority has a granularity of 2; this means that we have 61 real
// priority levels: 60 to map BeOS priorities 1-120, plus the idle priority (0).
static struct thread_queue run_q[(B_MAX_PRIORITY / 2) + 1] = { { NULL, NULL }, };
#else /* NEW_SCHEDULER */
// The dead queue is used as a pool from which to retrieve and reuse previously
// allocated thread structs when creating a new thread. It should be gone once
// the slab allocator is in.
#endif /* NEW_SCHEDULER */
struct thread_queue dead_q;
static void thread_kthread_entry(void);
static void thread_kthread_exit(void);
//static void deliver_signal(struct thread *t, int signal);
// insert a thread onto the tail of a queue
@@ -140,33 +132,6 @@ thread_dequeue_id(struct thread_queue *q, thread_id thr_id)
return t;
}
#ifndef NEW_SCHEDULER
struct thread *
thread_lookat_run_q(int priority)
{
return thread_lookat_queue(&run_q[(priority + 1) >> 1]);
}
void
thread_enqueue_run_q(struct thread *t)
{
// these shouldn't exist
if (t->priority > B_MAX_PRIORITY)
t->priority = B_MAX_PRIORITY;
else if (t->priority < B_MIN_PRIORITY)
t->priority = B_MIN_PRIORITY;
thread_enqueue(t, &run_q[(t->priority + 1) >> 1]);
}
struct thread *
thread_dequeue_run_q(int priority)
{
return thread_dequeue(&run_q[(priority + 1) >> 1]);
}
#endif /* not NEW_SCHEDULER */
static void
insert_thread_into_team(struct team *p, struct thread *t)
@@ -482,52 +447,6 @@ thread_resume_thread(thread_id id)
}
#ifndef NEW_SCHEDULER
status_t
thread_set_priority(thread_id id, int32 priority)
{
struct thread *t;
int retval;
// make sure the passed in priority is within bounds
if (priority > B_MAX_PRIORITY)
priority = B_MAX_PRIORITY;
if (priority < B_MIN_PRIORITY)
priority = B_MIN_PRIORITY;
t = thread_get_current_thread();
if (t->id == id) {
// it's ourself, so we know we aren't in a run queue, and we can manipulate
// our structure directly
t->priority = priority;
retval = B_NO_ERROR;
} else {
int state = disable_interrupts();
GRAB_THREAD_LOCK();
t = thread_get_thread_struct_locked(id);
if (t) {
if (t->state == B_THREAD_READY && t->priority != priority) {
// this thread is in a ready queue right now, so it needs to be reinserted
thread_dequeue_id(&run_q[(t->priority + 1) >> 1], t->id);
t->priority = priority;
thread_enqueue_run_q(t);
} else
t->priority = priority;
retval = B_NO_ERROR;
} else
retval = ERR_INVALID_HANDLE;
RELEASE_THREAD_LOCK();
restore_interrupts(state);
}
return retval;
}
#endif /* not NEW_SCHEDULER */
static const char *
state_to_text(int state)
{
@@ -607,11 +526,12 @@ dump_thread_info(int argc, char **argv)
// if the argument looks like a hex number, treat it as such
if (strlen(argv[1]) > 2 && argv[1][0] == '0' && argv[1][1] == 'x') {
num = atoul(argv[1]);
if(num > vm_get_kernel_aspace()->virtual_map.base) {
/* if(num > vm_get_kernel_aspace()->virtual_map.base) {
// XXX semi-hack
_dump_thread_info((struct thread *)num);
return 0;
} else
*/
id = num;
}
@@ -783,11 +703,6 @@ thread_init(kernel_args *ka)
thread_hash = hash_init(15, (addr)&t->all_next - (addr)t,
&thread_struct_compare, &thread_struct_hash);
#ifndef NEW_SCHEDULER
// zero out the run queues
memset(run_q, 0, sizeof(run_q));
#endif /* not NEW_SCHEDULER */
// zero out the dead thread structure q
memset(&dead_q, 0, sizeof(dead_q));
@@ -978,7 +893,7 @@ thread_exit(void)
(int)t->return_code);
// boost our priority to get this over with
thread_set_priority(t->id, B_FIRST_REAL_TIME_PRIORITY);
t->priority = B_FIRST_REAL_TIME_PRIORITY;
// Cancel previously installed alarm timer, if any
cancel_timer(&t->alarm);
+1 -1
View File
@@ -149,7 +149,7 @@ has_data(thread_id thread)
status_t
snooze(bigtime_t microseconds)
{
return sys_snooze_until(system_time() + microseconds, B_SYSTEM_TIMEBASE);
return sys_snooze_until(sys_system_time() + microseconds, B_SYSTEM_TIMEBASE);
}