diff --git a/module/dispatcher/dispatcher.cpp b/module/dispatcher/dispatcher.cpp index cad8071..aeaab20 100644 --- a/module/dispatcher/dispatcher.cpp +++ b/module/dispatcher/dispatcher.cpp @@ -15,8 +15,14 @@ void dispatcher::dispatcher::timer_test_callback() { } void dispatcher::dispatcher::init_timer_callbacks() { + std::optional result = this->timers.insert_callback( + std::bind(&dispatcher::dispatcher::timer_test_callback, this), 5, 5); + this->timers.insert_callback( + std::bind(&dispatcher::dispatcher::timer_test_callback, this), 7, 7); this->timers.insert_callback( std::bind(&dispatcher::dispatcher::timer_test_callback, this), 10, 10); + + this->timers.remove_callback(result.value()); } void dispatcher::dispatcher::run_timer_thread() { @@ -32,10 +38,10 @@ void dispatcher::dispatcher::run() { this->init_timer_callbacks(); this->run_timer_thread(); this->run_io_port_thread(); - thread_pool.queue_job([this]() { k_interface.run_completion_port(); }); + //thread_pool.queue_job([this]() { k_interface.run_completion_port(); }); while (true) { - this->issue_kernel_job(); - helper::sleep_thread(DISPATCH_LOOP_SLEEP_TIME); + //this->issue_kernel_job(); + //helper::sleep_thread(DISPATCH_LOOP_SLEEP_TIME); } } diff --git a/module/dispatcher/timer.cpp b/module/dispatcher/timer.cpp index c4e7027..a702879 100644 --- a/module/dispatcher/timer.cpp +++ b/module/dispatcher/timer.cpp @@ -3,7 +3,12 @@ #include "../common.h" #include "../helper.h" -dispatcher::timer::timer() { this->active_callbacks = 0; } +dispatcher::timer::timer() { + this->active_callbacks = 0; + for (auto &entry : handles) { + entry = INVALID_HANDLE_VALUE; + } +} dispatcher::timer::~timer() {} @@ -18,65 +23,94 @@ bool dispatcher::timer::set_timer_object(HANDLE handle, LARGE_INTEGER *due_time, : false; } -bool dispatcher::timer::insert_callback(std::function routine, - int due_time_seconds, - int period_seconds) { +dispatcher::timer::callback::callback(std::function routine, + int due_time_seconds, + int period_seconds) { + this->callback_routine = routine; + this->due_time.QuadPart = helper::seconds_to_nanoseconds(due_time_seconds); + this->period = helper::seconds_to_milliseconds(period_seconds); +} + +std::optional +dispatcher::timer::insert_callback(std::function routine, + int due_time_seconds, int period_seconds) { std::lock_guard lock(this->lock); - std::optional index = this->find_free_handle_index(); - if (!index.has_value()) { + std::optional handle = this->find_free_handle(); + if (!handle.has_value()) { LOG_ERROR("No free event handles available. Unable to create timer."); - return false; + return {}; } - HANDLE handle = create_timer_object(); - if (!handle) { + *handle.value() = create_timer_object(); + if (*handle.value() == NULL) { LOG_ERROR("CreateWaitableTimer failed with status %x", GetLastError()); - set_callback_inactive(index.value()); - return false; + return {}; } - callback *cb = &this->callbacks[index.value()]; - cb->callback_routine = routine; - cb->due_time.QuadPart = helper::seconds_to_nanoseconds(due_time_seconds); - cb->period = helper::seconds_to_milliseconds(period_seconds); - - this->handles[index.value()] = handle; - if (!set_timer_object(handle, &cb->due_time, cb->period)) { + callback cb(routine, due_time_seconds, period_seconds); + if (!set_timer_object(*handle.value(), &cb.due_time, cb.period)) { LOG_ERROR("SetWaitableTimer failed with status %x", GetLastError()); - close_handle_entry(handle); - set_callback_inactive(index.value()); } + std::pair entry(*handle.value(), cb); + this->callbacks.insert(entry); + this->insert_handle(*handle.value()); this->active_callbacks++; - return true; + return *handle.value(); } /* assumes lock is held by caller */ -std::optional dispatcher::timer::find_free_handle_index() { +std::optional dispatcher::timer::find_free_handle() { for (int index = 0; index < MAXIMUM_WAIT_OBJECTS; index++) { - if (callbacks[index].in_use == false) { - callbacks[index].in_use = true; - return index; - } + if (handles[index] == INVALID_HANDLE_VALUE) + return &handles[index]; } return {}; } -void dispatcher::timer::close_handle_entry(HANDLE handle) { - for (auto &entry : handles) { - if (entry == handle) { - entry = INVALID_HANDLE_VALUE; - CloseHandle(entry); +/* assumes lock is held */ +void dispatcher::timer::insert_handle(HANDLE handle) { + for (HANDLE entry : this->handles) { + if (entry == INVALID_HANDLE_VALUE) { + entry = handle; + return; } } } -void dispatcher::timer::set_callback_inactive(int index) { - this->callbacks[index].in_use = false; +/* assumes lock is held */ +void dispatcher::timer::close_handle_entry(HANDLE handle) { + this->callbacks.erase(handle); + for (int entry = 0; entry < MAXIMUM_WAIT_OBJECTS; entry++) { + if (this->handles[entry] == handle) { + CloseHandle(handle); + this->handles[entry] = INVALID_HANDLE_VALUE; + /* ordering doesnt matter, aslong as the valid handles are at the front of + * the array and are contiguous */ + std::sort(this->handles.begin(), this->handles.end()); + this->active_callbacks--; + return; + } + } } void dispatcher::timer::dispatch_callback_for_index(unsigned long index) { - this->callbacks[index].callback_routine(); + std::unordered_map::const_iterator it = + this->callbacks.find(handles[index]); + if (it == this->callbacks.end()) + return; + it->second.callback_routine(); +} + +/* assumes lock is held */ +void dispatcher::timer::query_removal_queue() { + if (callbacks_to_remove.empty()) + return; + while (!callbacks_to_remove.empty()) { + HANDLE entry = callbacks_to_remove.front(); + this->close_handle_entry(entry); + this->callbacks_to_remove.pop(); + } } void dispatcher::timer::run_timer_thread() { @@ -84,6 +118,22 @@ void dispatcher::timer::run_timer_thread() { unsigned long index = WaitForMultipleObjects( this->active_callbacks, reinterpret_cast(&handles), false, INFINITE); - this->dispatch_callback_for_index(index); + { + std::lock_guard lock(this->lock); + this->dispatch_callback_for_index(index); + this->query_removal_queue(); + } } +} + +/* + * If we remove a callback whilst the main loop is sleeping, it means the + * information passed to KeWaitForMultipleObjects will be wrong, hence we need + * to wait until our thread is run by the scheduler, perform the operation for + * the alerted handle and THEN remove any entries from the removal queue. Then + * once we recall KeWaitForMultipleObjects the new handle array will be valid. + */ +void dispatcher::timer::remove_callback(HANDLE handle) { + std::lock_guard lock(this->lock); + this->callbacks_to_remove.push(handle); } \ No newline at end of file diff --git a/module/dispatcher/timer.h b/module/dispatcher/timer.h index 2eb43b5..3594a2f 100644 --- a/module/dispatcher/timer.h +++ b/module/dispatcher/timer.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include /* * array of handles which we pass to WaitForMultipleEvents @@ -38,28 +40,34 @@ class timer { std::function callback_routine; LARGE_INTEGER due_time; unsigned long period; + + callback(std::function routine, int due_time_seconds, + int period_seconds); }; - std::optional find_free_handle_index(); + std::optional find_free_handle(); void close_handle_entry(HANDLE handle); void dispatch_callback_for_index(unsigned long index); HANDLE create_timer_object(); bool set_timer_object(HANDLE handle, LARGE_INTEGER *due_time, unsigned long period); - void set_callback_inactive(int index); + void query_removal_queue(); + void insert_handle(HANDLE handle); public: std::mutex lock; std::array handles; - std::array callbacks; + std::unordered_map callbacks; + std::queue callbacks_to_remove; int active_callbacks; timer(); ~timer(); - bool insert_callback(std::function routine, int due_time_seconds, + std::optional insert_callback(std::function routine, int due_time_seconds, int period_seconds); + void remove_callback(HANDLE handle); void run_timer_thread(); }; } // namespace dispatcher \ No newline at end of file diff --git a/module/main.cpp b/module/main.cpp index f6b53e5..61b6e12 100644 --- a/module/main.cpp +++ b/module/main.cpp @@ -2,7 +2,10 @@ #include "module.h" -DWORD WINAPI Init(HINSTANCE hinstDLL) { module::run(hinstDLL); } +DWORD WINAPI Init(HINSTANCE hinstDLL) { + module::run(hinstDLL); + return 0; +} BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { diff --git a/module/module.vcxproj b/module/module.vcxproj index 0747bf3..e9cc82c 100644 --- a/module/module.vcxproj +++ b/module/module.vcxproj @@ -110,8 +110,9 @@ true _DEBUG;MODULE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true - Use + NotUsing pch.h + stdcpp20 Windows diff --git a/module/module.vcxproj.filters b/module/module.vcxproj.filters index ee19eb0..8f65ff8 100644 --- a/module/module.vcxproj.filters +++ b/module/module.vcxproj.filters @@ -1,87 +1,27 @@  - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - + + + + + + + + + + - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - -um-rewrite-final - - Source Files - -======= -master - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - -um-rewrite-final - - Header Files - -======= -master + + + + + + + + + + \ No newline at end of file