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;
|
struct interrupt_context;
|
||||||
|
|
||||||
|
class Thread;
|
||||||
|
|
||||||
struct interrupt_handler
|
struct interrupt_handler
|
||||||
{
|
{
|
||||||
void (*handler)(struct interrupt_context*, void*);
|
void (*handler)(struct interrupt_context*, void*);
|
||||||
|
@ -122,6 +124,9 @@ void Init();
|
||||||
void WorkerThread(void* user);
|
void WorkerThread(void* user);
|
||||||
void ScheduleWork(struct interrupt_work* work);
|
void ScheduleWork(struct interrupt_work* work);
|
||||||
|
|
||||||
|
extern Thread* interrupt_worker_thread;
|
||||||
|
extern bool interrupt_worker_thread_boost;
|
||||||
|
|
||||||
} // namespace Interrupt
|
} // namespace Interrupt
|
||||||
} // namespace Sortix
|
} // 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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -49,6 +49,7 @@ static inline void ExitThread()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Switch(struct interrupt_context* intctx);
|
void Switch(struct interrupt_context* intctx);
|
||||||
|
void SwitchTo(struct interrupt_context* intctx, Thread* new_thread);
|
||||||
void SetThreadState(Thread* thread, ThreadState state);
|
void SetThreadState(Thread* thread, ThreadState state);
|
||||||
ThreadState GetThreadState(Thread* thread);
|
ThreadState GetThreadState(Thread* thread);
|
||||||
void SetIdleThread(Thread* thread);
|
void SetIdleThread(Thread* thread);
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
namespace Interrupt {
|
namespace Interrupt {
|
||||||
|
|
||||||
|
Thread* interrupt_worker_thread = NULL;
|
||||||
|
bool interrupt_worker_thread_boost = false;
|
||||||
|
|
||||||
static struct interrupt_work* first;
|
static struct interrupt_work* first;
|
||||||
static struct interrupt_work* last;
|
static struct interrupt_work* last;
|
||||||
|
|
||||||
|
@ -63,6 +66,7 @@ void ScheduleWork(struct interrupt_work* work)
|
||||||
(last ? last->next : first) = work;
|
(last ? last->next : first) = work;
|
||||||
work->next = NULL;
|
work->next = NULL;
|
||||||
last = work;
|
last = work;
|
||||||
|
interrupt_worker_thread_boost = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Interrupt
|
} // namespace Interrupt
|
||||||
|
|
|
@ -423,16 +423,17 @@ static void BootThread(void* /*user*/)
|
||||||
|
|
||||||
// Let's create the interrupt worker thread that executes additional work
|
// Let's create the interrupt worker thread that executes additional work
|
||||||
// requested by interrupt handlers, where such work isn't safe.
|
// requested by interrupt handlers, where such work isn't safe.
|
||||||
Thread* interruptworker = RunKernelThread(Interrupt::WorkerThread, NULL);
|
Interrupt::interrupt_worker_thread =
|
||||||
if ( !interruptworker )
|
RunKernelThread(Interrupt::WorkerThread, NULL);
|
||||||
|
if ( !Interrupt::interrupt_worker_thread )
|
||||||
Panic("Could not create interrupt worker");
|
Panic("Could not create interrupt worker");
|
||||||
|
|
||||||
// Initialize the worker thread data structures.
|
// Initialize the worker thread data structures.
|
||||||
Worker::Init();
|
Worker::Init();
|
||||||
|
|
||||||
// Create a general purpose worker thread.
|
// Create a general purpose worker thread.
|
||||||
Thread* workerthread = RunKernelThread(Worker::Thread, NULL);
|
Thread* worker_thread = RunKernelThread(Worker::Thread, NULL);
|
||||||
if ( !workerthread )
|
if ( !worker_thread )
|
||||||
Panic("Unable to create general purpose 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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static void SwitchRegisters(struct interrupt_context* intctx,
|
||||||
void SwitchThread(struct interrupt_context* intctx, Thread* prev, Thread* next)
|
Thread* prev,
|
||||||
|
Thread* next)
|
||||||
{
|
{
|
||||||
if ( prev == next )
|
if ( prev == next )
|
||||||
return;
|
return;
|
||||||
|
@ -264,6 +265,31 @@ void SwitchThread(struct interrupt_context* intctx, Thread* prev, Thread* next)
|
||||||
current_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* idle_thread;
|
||||||
static Thread* first_runnable_thread;
|
static Thread* first_runnable_thread;
|
||||||
static Thread* true_current_thread;
|
static Thread* true_current_thread;
|
||||||
|
@ -308,29 +334,21 @@ static Thread* PopNextThread(bool yielded)
|
||||||
return result;
|
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)
|
static void RealSwitch(struct interrupt_context* intctx, bool yielded)
|
||||||
{
|
{
|
||||||
Thread* old_thread = CurrentThread();
|
Thread* old_thread = CurrentThread();
|
||||||
Thread* new_thread = PopNextThread(yielded);
|
Thread* new_thread = PopNextThread(yielded);
|
||||||
SwitchThread(intctx, old_thread, new_thread);
|
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)
|
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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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.
|
// Send an end of interrupt signal to the PICs if we got an IRQ.
|
||||||
if ( IRQ0 <= int_no && int_no <= IRQ15 )
|
if ( IRQ0 <= int_no && int_no <= IRQ15 )
|
||||||
PIC::SendEOI(int_no - IRQ0);
|
PIC::SendEOI(int_no - IRQ0);
|
||||||
|
|
||||||
|
if ( interrupt_worker_thread_boost )
|
||||||
|
{
|
||||||
|
interrupt_worker_thread_boost = false;
|
||||||
|
Scheduler::SwitchTo(intctx, interrupt_worker_thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Interrupt
|
} // namespace Interrupt
|
||||||
|
|
Loading…
Reference in a new issue