From 5e7d6a17a03af89a05c1a96fb6a3508b954750ec Mon Sep 17 00:00:00 2001 From: lillo Date: Thu, 31 Oct 2002 13:20:00 +0000 Subject: [PATCH] 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 --- headers/private/kernel/thread.h | 9 --- src/kernel/apps/tests/thread_test.c | 7 +- src/kernel/core/scheduler.c | 111 +++++++--------------------- src/kernel/core/sem.c | 8 +- src/kernel/core/signal.c | 7 +- src/kernel/core/thread.c | 91 +---------------------- src/kernel/libroot/os/thread.c | 2 +- 7 files changed, 42 insertions(+), 193 deletions(-) diff --git a/headers/private/kernel/thread.h b/headers/private/kernel/thread.h index 5349955c09..439a905e3d 100755 --- a/headers/private/kernel/thread.h +++ b/headers/private/kernel/thread.h @@ -13,9 +13,6 @@ extern "C" { #include #include -// 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); diff --git a/src/kernel/apps/tests/thread_test.c b/src/kernel/apps/tests/thread_test.c index 573a800b62..f3b074bfa3 100644 --- a/src/kernel/apps/tests/thread_test.c +++ b/src/kernel/apps/tests/thread_test.c @@ -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++) { diff --git a/src/kernel/core/scheduler.c b/src/kernel/core/scheduler.c index 50be485a69..998f173cab 100644 --- a/src/kernel/core/scheduler.c +++ b/src/kernel/core/scheduler.c @@ -18,17 +18,33 @@ #include #include #include -#ifdef NEW_SCHEDULER #include #include -#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 */ } diff --git a/src/kernel/core/sem.c b/src/kernel/core/sem.c index 50c5a65d60..f3f27b68fb 100644 --- a/src/kernel/core/sem.c +++ b/src/kernel/core/sem.c @@ -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); diff --git a/src/kernel/core/signal.c b/src/kernel/core/signal.c index 053690a874..2eb1feab81 100644 --- a/src/kernel/core/signal.c +++ b/src/kernel/core/signal.c @@ -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; } diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index de8b4c265e..26d0b0cab9 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -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); diff --git a/src/kernel/libroot/os/thread.c b/src/kernel/libroot/os/thread.c index ab5ba02cde..ad0379d7bb 100644 --- a/src/kernel/libroot/os/thread.c +++ b/src/kernel/libroot/os/thread.c @@ -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); }