Adding deferred xoverlapped completion helper.
This commit is contained in:
parent
c9f4d00da3
commit
5b2f049d4c
|
@ -36,6 +36,8 @@ DEFINE_string(content_root, "content",
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
|
||||||
|
constexpr uint32_t kDeferredOverlappedDelayMillis = 100;
|
||||||
|
|
||||||
// This is a global object initialized with the XboxkrnlModule.
|
// This is a global object initialized with the XboxkrnlModule.
|
||||||
// It references the current kernel state object that all kernel methods should
|
// It references the current kernel state object that all kernel methods should
|
||||||
// be using to stash their variables.
|
// be using to stash their variables.
|
||||||
|
@ -88,6 +90,12 @@ KernelState::KernelState(Emulator* emulator)
|
||||||
KernelState::~KernelState() {
|
KernelState::~KernelState() {
|
||||||
SetExecutableModule(nullptr);
|
SetExecutableModule(nullptr);
|
||||||
|
|
||||||
|
if (dispatch_thread_running_) {
|
||||||
|
dispatch_thread_running_ = false;
|
||||||
|
dispatch_cond_.notify_all();
|
||||||
|
dispatch_thread_->Wait(0, 0, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
if (process_info_block_address_) {
|
if (process_info_block_address_) {
|
||||||
memory_->SystemHeapFree(process_info_block_address_);
|
memory_->SystemHeapFree(process_info_block_address_);
|
||||||
}
|
}
|
||||||
|
@ -202,6 +210,30 @@ void KernelState::SetExecutableModule(object_ref<XUserModule> module) {
|
||||||
memory()->TranslateVirtual<xe::be<uint32_t>*>(export->variable_ptr);
|
memory()->TranslateVirtual<xe::be<uint32_t>*>(export->variable_ptr);
|
||||||
*variable_ptr = executable_module_->hmodule_ptr();
|
*variable_ptr = executable_module_->hmodule_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Spin up deferred dispatch worker.
|
||||||
|
// TODO(benvanik): move someplace more appropriate (out of ctor, but around
|
||||||
|
// here).
|
||||||
|
assert_false(dispatch_thread_running_);
|
||||||
|
dispatch_thread_running_ = true;
|
||||||
|
dispatch_thread_ =
|
||||||
|
object_ref<XHostThread>(new XHostThread(this, 128 * 1024, 0, [this]() {
|
||||||
|
while (dispatch_thread_running_) {
|
||||||
|
std::unique_lock<std::mutex> lock(dispatch_mutex_);
|
||||||
|
if (dispatch_queue_.empty()) {
|
||||||
|
dispatch_cond_.wait(lock);
|
||||||
|
if (!dispatch_thread_running_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto fn = std::move(dispatch_queue_.front());
|
||||||
|
dispatch_queue_.pop_front();
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}));
|
||||||
|
dispatch_thread_->set_name("Kernel Dispatch Thread");
|
||||||
|
dispatch_thread_->Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::LoadKernelModule(object_ref<XKernelModule> kernel_module) {
|
void KernelState::LoadKernelModule(object_ref<XKernelModule> kernel_module) {
|
||||||
|
@ -430,5 +462,30 @@ void KernelState::CompleteOverlappedImmediateEx(uint32_t overlapped_ptr,
|
||||||
CompleteOverlappedEx(overlapped_ptr, result, extended_error, length);
|
CompleteOverlappedEx(overlapped_ptr, result, extended_error, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KernelState::CompleteOverlappedDeferred(
|
||||||
|
std::function<void()> completion_callback, uint32_t overlapped_ptr,
|
||||||
|
X_RESULT result) {
|
||||||
|
CompleteOverlappedDeferredEx(std::move(completion_callback), overlapped_ptr,
|
||||||
|
result, result, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KernelState::CompleteOverlappedDeferredEx(
|
||||||
|
std::function<void()> completion_callback, uint32_t overlapped_ptr,
|
||||||
|
X_RESULT result, uint32_t extended_error, uint32_t length) {
|
||||||
|
auto ptr = memory()->TranslateVirtual(overlapped_ptr);
|
||||||
|
XOverlappedSetResult(ptr, X_ERROR_IO_PENDING);
|
||||||
|
XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle());
|
||||||
|
std::unique_lock<std::mutex> lock(dispatch_mutex_);
|
||||||
|
dispatch_queue_.push_back([this, completion_callback, overlapped_ptr, result,
|
||||||
|
extended_error, length]() {
|
||||||
|
xe::threading::Sleep(
|
||||||
|
std::chrono::milliseconds::duration(kDeferredOverlappedDelayMillis));
|
||||||
|
completion_callback();
|
||||||
|
auto ptr = memory()->TranslateVirtual(overlapped_ptr);
|
||||||
|
CompleteOverlappedEx(overlapped_ptr, result, extended_error, length);
|
||||||
|
});
|
||||||
|
dispatch_cond_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
@ -38,6 +42,7 @@ namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
|
||||||
class Dispatcher;
|
class Dispatcher;
|
||||||
|
class XHostThread;
|
||||||
class XKernelModule;
|
class XKernelModule;
|
||||||
class XModule;
|
class XModule;
|
||||||
class XNotifyListener;
|
class XNotifyListener;
|
||||||
|
@ -133,6 +138,11 @@ class KernelState {
|
||||||
void CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result);
|
void CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result);
|
||||||
void CompleteOverlappedImmediateEx(uint32_t overlapped_ptr, X_RESULT result,
|
void CompleteOverlappedImmediateEx(uint32_t overlapped_ptr, X_RESULT result,
|
||||||
uint32_t extended_error, uint32_t length);
|
uint32_t extended_error, uint32_t length);
|
||||||
|
void CompleteOverlappedDeferred(std::function<void()> completion_callback,
|
||||||
|
uint32_t overlapped_ptr, X_RESULT result);
|
||||||
|
void CompleteOverlappedDeferredEx(std::function<void()> completion_callback,
|
||||||
|
uint32_t overlapped_ptr, X_RESULT result,
|
||||||
|
uint32_t extended_error, uint32_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadKernelModule(object_ref<XKernelModule> kernel_module);
|
void LoadKernelModule(object_ref<XKernelModule> kernel_module);
|
||||||
|
@ -161,6 +171,12 @@ class KernelState {
|
||||||
|
|
||||||
uint32_t process_info_block_address_;
|
uint32_t process_info_block_address_;
|
||||||
|
|
||||||
|
std::atomic<bool> dispatch_thread_running_ = false;
|
||||||
|
object_ref<XHostThread> dispatch_thread_;
|
||||||
|
std::mutex dispatch_mutex_;
|
||||||
|
std::condition_variable dispatch_cond_;
|
||||||
|
std::list<std::function<void()>> dispatch_queue_;
|
||||||
|
|
||||||
friend class XObject;
|
friend class XObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue