mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Prioritize the interrupt worker thread.
This commit is contained in:
parent
66e5ddcfab
commit
9f1965f36e
6 changed files with 61 additions and 26 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
Loading…
Reference in a new issue