Commit 9f1965f3 authored by Jonas Termansen's avatar Jonas Termansen

Prioritize the interrupt worker thread.

parent 66e5ddcf
......@@ -29,6 +29,8 @@ namespace Sortix {
struct interrupt_context;
class Thread;
struct interrupt_handler
{
void (*handler)(struct interrupt_context*, void*);
......@@ -122,6 +124,9 @@ void Init();
void WorkerThread(void* user);
void ScheduleWork(struct interrupt_work* work);
extern Thread* interrupt_worker_thread;
extern bool interrupt_worker_thread_boost;
} // namespace Interrupt
} // namespace Sortix
......
/*
* Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen.
* Copyright (c) 2011, 2012, 2013, 2014, 2017 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -49,6 +49,7 @@ static inline void ExitThread()
#endif
void Switch(struct interrupt_context* intctx);
void SwitchTo(struct interrupt_context* intctx, Thread* new_thread);
void SetThreadState(Thread* thread, ThreadState state);
ThreadState GetThreadState(Thread* thread);
void SetIdleThread(Thread* thread);
......
......@@ -28,6 +28,9 @@
namespace Sortix {
namespace Interrupt {
Thread* interrupt_worker_thread = NULL;
bool interrupt_worker_thread_boost = false;
static struct interrupt_work* first;
static struct interrupt_work* last;
......@@ -63,6 +66,7 @@ void ScheduleWork(struct interrupt_work* work)
(last ? last->next : first) = work;
work->next = NULL;
last = work;
interrupt_worker_thread_boost = true;
}
} // namespace Interrupt
......
......@@ -423,16 +423,17 @@ static void BootThread(void* /*user*/)
// Let's create the interrupt worker thread that executes additional work
// requested by interrupt handlers, where such work isn't safe.
Thread* interruptworker = RunKernelThread(Interrupt::WorkerThread, NULL);
if ( !interruptworker )
Interrupt::interrupt_worker_thread =
RunKernelThread(Interrupt::WorkerThread, NULL);
if ( !Interrupt::interrupt_worker_thread )
Panic("Could not create interrupt worker");
// Initialize the worker thread data structures.
Worker::Init();
// Create a general purpose worker thread.
Thread* workerthread = RunKernelThread(Worker::Thread, NULL);
if ( !workerthread )
Thread* worker_thread = RunKernelThread(Worker::Thread, NULL);
if ( !worker_thread )
Panic("Unable to create general purpose worker thread");
//
......
......@@ -248,8 +248,9 @@ static void FakeInterruptedContext(struct interrupt_context* intctx, int int_no)
#endif
}
static
void SwitchThread(struct interrupt_context* intctx, Thread* prev, Thread* next)
static void SwitchRegisters(struct interrupt_context* intctx,
Thread* prev,
Thread* next)
{
if ( prev == next )
return;
......@@ -264,6 +265,31 @@ void SwitchThread(struct interrupt_context* intctx, Thread* prev, Thread* next)
current_thread = next;
}
static void SwitchThread(struct interrupt_context* intctx,
Thread* old_thread,
Thread* new_thread)
{
SwitchRegisters(intctx, old_thread, new_thread);
if ( intctx->signal_pending && InUserspace(intctx) )
{
// Become the thread for real and run the signal handler.
if ( old_thread == new_thread )
{
// We're already this thread, so run the signal handler.
Interrupt::Enable();
assert(Interrupt::IsEnabled());
Signal::DispatchHandler(intctx, NULL);
}
else
{
// We need to transfer execution to the correct stack. We know the
// the thread is in user-space and isn't using its kernel stack, and
// we know we're not using the stack right now.
FakeInterruptedContext(intctx, 130);
}
}
}
static Thread* idle_thread;
static Thread* first_runnable_thread;
static Thread* true_current_thread;
......@@ -308,29 +334,21 @@ static Thread* PopNextThread(bool yielded)
return result;
}
void SwitchTo(struct interrupt_context* intctx, Thread* new_thread)
{
Thread* old_thread = CurrentThread();
if ( new_thread == old_thread )
return;
first_runnable_thread = old_thread;
true_current_thread = new_thread;
SwitchThread(intctx, old_thread, new_thread);
}
static void RealSwitch(struct interrupt_context* intctx, bool yielded)
{
Thread* old_thread = CurrentThread();
Thread* new_thread = PopNextThread(yielded);
SwitchThread(intctx, old_thread, new_thread);
if ( intctx->signal_pending && InUserspace(intctx) )
{
// Become the thread for real and run the signal handler.
if ( old_thread == new_thread )
{
// We're already this thread, so run the signal handler.
Interrupt::Enable();
assert(Interrupt::IsEnabled());
Signal::DispatchHandler(intctx, NULL);
}
else
{
// We need to transfer execution to the correct stack. We know the
// the thread is in user-space and isn't using its kernel stack, and
// we know we're not using the stack right now.
FakeInterruptedContext(intctx, 130);
}
}
}
void Switch(struct interrupt_context* intctx)
......
/*
* Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen.
* Copyright (c) 2011, 2012, 2013, 2014, 2017 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
......@@ -357,6 +357,12 @@ extern "C" void interrupt_handler(struct interrupt_context* intctx)
// Send an end of interrupt signal to the PICs if we got an IRQ.
if ( IRQ0 <= int_no && int_no <= IRQ15 )
PIC::SendEOI(int_no - IRQ0);
if ( interrupt_worker_thread_boost )
{
interrupt_worker_thread_boost = false;
Scheduler::SwitchTo(intctx, interrupt_worker_thread);
}
}
} // namespace Interrupt
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment