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:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user