Switching audio system to platform-agnostic primitives.

This commit is contained in:
Ben Vanik 2015-07-14 23:13:56 -07:00
parent 345fe60da0
commit a6012b73f4
13 changed files with 150 additions and 165 deletions

View File

@ -73,19 +73,14 @@ AudioSystem::AudioSystem(Emulator* emulator)
} }
for (size_t i = 0; i < kMaximumClientCount; ++i) { for (size_t i = 0; i < kMaximumClientCount; ++i) {
client_semaphores_[i] = client_semaphores_[i] =
CreateSemaphore(NULL, 0, kMaximumQueuedFrames, NULL); xe::threading::Semaphore::Create(0, kMaximumQueuedFrames);
wait_handles_[i] = client_semaphores_[i]; wait_handles_[i] = client_semaphores_[i].get();
} }
shutdown_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); shutdown_event_ = xe::threading::Event::CreateManualResetEvent(false);
wait_handles_[kMaximumClientCount] = shutdown_event_; wait_handles_[kMaximumClientCount] = shutdown_event_.get();
} }
AudioSystem::~AudioSystem() { AudioSystem::~AudioSystem() = default;
for (size_t i = 0; i < kMaximumClientCount; ++i) {
CloseHandle(client_semaphores_[i]);
}
CloseHandle(shutdown_event_);
}
X_STATUS AudioSystem::Setup() { X_STATUS AudioSystem::Setup() {
processor_ = emulator_->processor(); processor_ = emulator_->processor();
@ -111,18 +106,17 @@ void AudioSystem::WorkerThreadMain() {
// Main run loop. // Main run loop.
while (worker_running_) { while (worker_running_) {
auto result = auto result = xe::threading::WaitAny(
WaitForMultipleObjectsEx(DWORD(xe::countof(wait_handles_)), wait_handles_, DWORD(xe::countof(wait_handles_)), true);
wait_handles_, FALSE, INFINITE, FALSE); if (result.first == xe::threading::WaitResult::kFailed ||
if (result == WAIT_FAILED || (result.first == xe::threading::WaitResult::kSuccess &&
result == WAIT_OBJECT_0 + kMaximumClientCount) { result.second == kMaximumClientCount)) {
continue; continue;
} }
size_t pumped = 0; size_t pumped = 0;
if (result >= WAIT_OBJECT_0 && if (result.first == xe::threading::WaitResult::kSuccess) {
result <= WAIT_OBJECT_0 + (kMaximumClientCount - 1)) { size_t index = result.second;
size_t index = result - WAIT_OBJECT_0;
do { do {
lock_.lock(); lock_.lock();
uint32_t client_callback = clients_[index].callback; uint32_t client_callback = clients_[index].callback;
@ -138,8 +132,9 @@ void AudioSystem::WorkerThreadMain() {
pumped++; pumped++;
index++; index++;
} while (index < kMaximumClientCount && } while (index < kMaximumClientCount &&
WaitForSingleObject(client_semaphores_[index], 0) == xe::threading::Wait(client_semaphores_[index].get(), false,
WAIT_OBJECT_0); std::chrono::milliseconds(0)) ==
xe::threading::WaitResult::kSuccess);
} }
if (!worker_running_) { if (!worker_running_) {
@ -160,7 +155,7 @@ void AudioSystem::Initialize() {}
void AudioSystem::Shutdown() { void AudioSystem::Shutdown() {
worker_running_ = false; worker_running_ = false;
SetEvent(shutdown_event_); shutdown_event_->Set();
worker_thread_->Wait(0, 0, 0, nullptr); worker_thread_->Wait(0, 0, 0, nullptr);
worker_thread_.reset(); worker_thread_.reset();
} }
@ -172,9 +167,9 @@ X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg,
auto index = unused_clients_.front(); auto index = unused_clients_.front();
auto client_semaphore = client_semaphores_[index]; auto client_semaphore = client_semaphores_[index].get();
BOOL ret = ReleaseSemaphore(client_semaphore, kMaximumQueuedFrames, NULL); auto ret = client_semaphore->Release(kMaximumQueuedFrames, nullptr);
assert_true(ret == TRUE); assert_true(ret);
AudioDriver* driver; AudioDriver* driver;
auto result = CreateDriver(index, client_semaphore, &driver); auto result = CreateDriver(index, client_semaphore, &driver);
@ -215,13 +210,14 @@ void AudioSystem::UnregisterClient(size_t index) {
clients_[index] = {0}; clients_[index] = {0};
unused_clients_.push(index); unused_clients_.push(index);
// drain the semaphore of its count // Drain the semaphore of its count.
auto client_semaphore = client_semaphores_[index]; auto client_semaphore = client_semaphores_[index].get();
DWORD wait_result; xe::threading::WaitResult wait_result;
do { do {
wait_result = WaitForSingleObject(client_semaphore, 0); wait_result = xe::threading::Wait(client_semaphore, false,
} while (wait_result == WAIT_OBJECT_0); std::chrono::milliseconds(0));
assert_true(wait_result == WAIT_TIMEOUT); } while (wait_result == xe::threading::WaitResult::kSuccess);
assert_true(wait_result == xe::threading::WaitResult::kTimeout);
} }
} // namespace apu } // namespace apu

View File

@ -14,11 +14,10 @@
#include <mutex> #include <mutex>
#include <queue> #include <queue>
#include "xenia/base/threading.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include "xenia/xbox.h" #include "xenia/xbox.h"
typedef void* HANDLE;
namespace xe { namespace xe {
namespace kernel { namespace kernel {
class XHostThread; class XHostThread;
@ -48,7 +47,15 @@ class AudioSystem {
void UnregisterClient(size_t index); void UnregisterClient(size_t index);
void SubmitFrame(size_t index, uint32_t samples_ptr); void SubmitFrame(size_t index, uint32_t samples_ptr);
virtual X_STATUS CreateDriver(size_t index, HANDLE semaphore, protected:
AudioSystem(Emulator* emulator);
virtual void Initialize();
void WorkerThreadMain();
virtual X_STATUS CreateDriver(size_t index,
xe::threading::Semaphore* semaphore,
AudioDriver** out_driver) = 0; AudioDriver** out_driver) = 0;
virtual void DestroyDriver(AudioDriver* driver) = 0; virtual void DestroyDriver(AudioDriver* driver) = 0;
@ -56,15 +63,6 @@ class AudioSystem {
// XAUDIO2_MAX_QUEUED_BUFFERS)) // XAUDIO2_MAX_QUEUED_BUFFERS))
static const size_t kMaximumQueuedFrames = 64; static const size_t kMaximumQueuedFrames = 64;
protected:
virtual void Initialize();
private:
void WorkerThreadMain();
protected:
AudioSystem(Emulator* emulator);
Emulator* emulator_; Emulator* emulator_;
Memory* memory_; Memory* memory_;
cpu::Processor* processor_; cpu::Processor* processor_;
@ -83,9 +81,11 @@ class AudioSystem {
uint32_t wrapped_callback_arg; uint32_t wrapped_callback_arg;
} clients_[kMaximumClientCount]; } clients_[kMaximumClientCount];
HANDLE client_semaphores_[kMaximumClientCount]; std::unique_ptr<xe::threading::Semaphore>
HANDLE shutdown_event_; // Event is always there in case we have no clients. client_semaphores_[kMaximumClientCount];
HANDLE wait_handles_[kMaximumClientCount + 1]; // Event is always there in case we have no clients.
std::unique_ptr<xe::threading::Event> shutdown_event_;
xe::threading::WaitHandle* wait_handles_[kMaximumClientCount + 1];
std::queue<size_t> unused_clients_; std::queue<size_t> unused_clients_;
}; };

View File

@ -23,7 +23,8 @@ NopAudioSystem::NopAudioSystem(Emulator* emulator) : AudioSystem(emulator) {}
NopAudioSystem::~NopAudioSystem() = default; NopAudioSystem::~NopAudioSystem() = default;
X_STATUS NopAudioSystem::CreateDriver(size_t index, HANDLE wait_handle, X_STATUS NopAudioSystem::CreateDriver(size_t index,
xe::threading::Semaphore* semaphore,
AudioDriver** out_driver) { AudioDriver** out_driver) {
return X_STATUS_NOT_IMPLEMENTED; return X_STATUS_NOT_IMPLEMENTED;
} }

View File

@ -23,7 +23,7 @@ class NopAudioSystem : public AudioSystem {
static std::unique_ptr<AudioSystem> Create(Emulator* emulator); static std::unique_ptr<AudioSystem> Create(Emulator* emulator);
X_STATUS CreateDriver(size_t index, HANDLE wait_handle, X_STATUS CreateDriver(size_t index, xe::threading::Semaphore* semaphore,
AudioDriver** out_driver) override; AudioDriver** out_driver) override;
void DestroyDriver(AudioDriver* driver) override; void DestroyDriver(AudioDriver* driver) override;
}; };

View File

@ -24,32 +24,27 @@ namespace xaudio2 {
class XAudio2AudioDriver::VoiceCallback : public IXAudio2VoiceCallback { class XAudio2AudioDriver::VoiceCallback : public IXAudio2VoiceCallback {
public: public:
VoiceCallback(HANDLE semaphore) : semaphore_(semaphore) {} VoiceCallback(xe::threading::Semaphore* semaphore) : semaphore_(semaphore) {}
~VoiceCallback() {} ~VoiceCallback() {}
void OnStreamEnd() {} void OnStreamEnd() {}
void OnVoiceProcessingPassEnd() {} void OnVoiceProcessingPassEnd() {}
void OnVoiceProcessingPassStart(uint32_t samples_required) {} void OnVoiceProcessingPassStart(uint32_t samples_required) {}
void OnBufferEnd(void* context) { void OnBufferEnd(void* context) {
BOOL ret = ReleaseSemaphore(semaphore_, 1, NULL); auto ret = semaphore_->Release(1, nullptr);
assert_true(ret == TRUE); assert_true(ret);
} }
void OnBufferStart(void* context) {} void OnBufferStart(void* context) {}
void OnLoopEnd(void* context) {} void OnLoopEnd(void* context) {}
void OnVoiceError(void* context, HRESULT result) {} void OnVoiceError(void* context, HRESULT result) {}
private: private:
HANDLE semaphore_; xe::threading::Semaphore* semaphore_ = nullptr;
}; };
XAudio2AudioDriver::XAudio2AudioDriver(Emulator* emulator, HANDLE semaphore) XAudio2AudioDriver::XAudio2AudioDriver(Emulator* emulator,
: AudioDriver(emulator), xe::threading::Semaphore* semaphore)
audio_(nullptr), : AudioDriver(emulator), semaphore_(semaphore) {
mastering_voice_(nullptr),
pcm_voice_(nullptr),
semaphore_(semaphore),
voice_callback_(nullptr),
current_frame_(0) {
static_assert(frame_count_ == XAUDIO2_MAX_QUEUED_BUFFERS, static_assert(frame_count_ == XAUDIO2_MAX_QUEUED_BUFFERS,
"xaudio header differs"); "xaudio header differs");
} }

View File

@ -22,7 +22,7 @@ namespace xaudio2 {
class XAudio2AudioDriver : public AudioDriver { class XAudio2AudioDriver : public AudioDriver {
public: public:
XAudio2AudioDriver(Emulator* emulator, HANDLE semaphore); XAudio2AudioDriver(Emulator* emulator, xe::threading::Semaphore* semaphore);
~XAudio2AudioDriver() override; ~XAudio2AudioDriver() override;
void Initialize(); void Initialize();
@ -30,13 +30,13 @@ class XAudio2AudioDriver : public AudioDriver {
void Shutdown(); void Shutdown();
private: private:
IXAudio2* audio_; IXAudio2* audio_ = nullptr;
IXAudio2MasteringVoice* mastering_voice_; IXAudio2MasteringVoice* mastering_voice_ = nullptr;
IXAudio2SourceVoice* pcm_voice_; IXAudio2SourceVoice* pcm_voice_ = nullptr;
HANDLE semaphore_; xe::threading::Semaphore* semaphore_ = nullptr;
class VoiceCallback; class VoiceCallback;
VoiceCallback* voice_callback_; VoiceCallback* voice_callback_ = nullptr;
static const uint32_t frame_count_ = 64; static const uint32_t frame_count_ = 64;
static const uint32_t frame_channels_ = 6; static const uint32_t frame_channels_ = 6;
@ -44,7 +44,7 @@ class XAudio2AudioDriver : public AudioDriver {
static const uint32_t frame_samples_ = frame_channels_ * channel_samples_; static const uint32_t frame_samples_ = frame_channels_ * channel_samples_;
static const uint32_t frame_size_ = sizeof(float) * frame_samples_; static const uint32_t frame_size_ = sizeof(float) * frame_samples_;
float frames_[frame_count_][frame_samples_]; float frames_[frame_count_][frame_samples_];
uint32_t current_frame_; uint32_t current_frame_ = 0;
}; };
} // namespace xaudio2 } // namespace xaudio2

View File

@ -30,7 +30,8 @@ XAudio2AudioSystem::~XAudio2AudioSystem() {}
void XAudio2AudioSystem::Initialize() { AudioSystem::Initialize(); } void XAudio2AudioSystem::Initialize() { AudioSystem::Initialize(); }
X_STATUS XAudio2AudioSystem::CreateDriver(size_t index, HANDLE semaphore, X_STATUS XAudio2AudioSystem::CreateDriver(size_t index,
xe::threading::Semaphore* semaphore,
AudioDriver** out_driver) { AudioDriver** out_driver) {
assert_not_null(out_driver); assert_not_null(out_driver);
auto driver = new XAudio2AudioDriver(emulator_, semaphore); auto driver = new XAudio2AudioDriver(emulator_, semaphore);

View File

@ -23,7 +23,7 @@ class XAudio2AudioSystem : public AudioSystem {
static std::unique_ptr<AudioSystem> Create(Emulator* emulator); static std::unique_ptr<AudioSystem> Create(Emulator* emulator);
X_RESULT CreateDriver(size_t index, HANDLE semaphore, X_RESULT CreateDriver(size_t index, xe::threading::Semaphore* semaphore,
AudioDriver** out_driver) override; AudioDriver** out_driver) override;
void DestroyDriver(AudioDriver* driver) override; void DestroyDriver(AudioDriver* driver) override;

View File

@ -111,83 +111,73 @@ class WaitHandle {
public: public:
virtual ~WaitHandle() = default; virtual ~WaitHandle() = default;
// Waits until the wait handle is in the signaled state, an alert triggers and
// a user callback is queued to the thread, or the timeout interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
inline WaitResult Wait(
bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitHandle::Wait(this, is_alertable, timeout);
}
// Waits until the wait handle is in the signaled state, an alert triggers and
// a user callback is queued to the thread, or the timeout interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
static WaitResult Wait(
WaitHandle* wait_handle, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
// Signals one object and waits on another object as a single operation.
// Waits until the wait handle is in the signaled state, an alert triggers and
// a user callback is queued to the thread, or the timeout interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
static WaitResult SignalAndWait(
WaitHandle* wait_handle_to_signal, WaitHandle* wait_handle_to_wait_on,
bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
// Waits until all of the specified objects are in the signaled state, a
// user callback is queued to the thread, or the time-out interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
inline static WaitResult WaitAll(
WaitHandle* wait_handles[], size_t wait_handle_count, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitMultiple(wait_handles, wait_handle_count, true, is_alertable,
timeout).first;
}
inline static WaitResult WaitAll(
std::vector<WaitHandle*> wait_handles, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitAll(wait_handles.data(), wait_handles.size(), is_alertable,
timeout);
}
// Waits until any of the specified objects are in the signaled state, a
// user callback is queued to the thread, or the time-out interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
// The second argument of the return tuple indicates which wait handle caused
// the wait to be satisfied or abandoned.
inline static std::pair<WaitResult, size_t> WaitAny(
WaitHandle* wait_handles[], size_t wait_handle_count, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitMultiple(wait_handles, wait_handle_count, false, is_alertable,
timeout);
}
inline static std::pair<WaitResult, size_t> WaitAny(
std::vector<WaitHandle*> wait_handles, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitAny(wait_handles.data(), wait_handles.size(), is_alertable,
timeout);
}
protected:
WaitHandle() = default;
// Returns the native handle of the object on the host system. // Returns the native handle of the object on the host system.
// This value is platform specific. // This value is platform specific.
virtual void* native_handle() const = 0; virtual void* native_handle() const = 0;
static std::pair<WaitResult, size_t> WaitMultiple( protected:
WaitHandle* wait_handles[], size_t wait_handle_count, bool wait_all, WaitHandle() = default;
bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
}; };
// Waits until the wait handle is in the signaled state, an alert triggers and
// a user callback is queued to the thread, or the timeout interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
WaitResult Wait(
WaitHandle* wait_handle, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
// Signals one object and waits on another object as a single operation.
// Waits until the wait handle is in the signaled state, an alert triggers and
// a user callback is queued to the thread, or the timeout interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
WaitResult SignalAndWait(
WaitHandle* wait_handle_to_signal, WaitHandle* wait_handle_to_wait_on,
bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
std::pair<WaitResult, size_t> WaitMultiple(
WaitHandle* wait_handles[], size_t wait_handle_count, bool wait_all,
bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
// Waits until all of the specified objects are in the signaled state, a
// user callback is queued to the thread, or the time-out interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
inline WaitResult WaitAll(
WaitHandle* wait_handles[], size_t wait_handle_count, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitMultiple(wait_handles, wait_handle_count, true, is_alertable,
timeout).first;
}
inline WaitResult WaitAll(
std::vector<WaitHandle*> wait_handles, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitAll(wait_handles.data(), wait_handles.size(), is_alertable,
timeout);
}
// Waits until any of the specified objects are in the signaled state, a
// user callback is queued to the thread, or the time-out interval elapses.
// If timeout is zero the call will return immediately instead of waiting and
// if the timeout is max() the wait will not time out.
// The second argument of the return tuple indicates which wait handle caused
// the wait to be satisfied or abandoned.
inline std::pair<WaitResult, size_t> WaitAny(
WaitHandle* wait_handles[], size_t wait_handle_count, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitMultiple(wait_handles, wait_handle_count, false, is_alertable,
timeout);
}
inline std::pair<WaitResult, size_t> WaitAny(
std::vector<WaitHandle*> wait_handles, bool is_alertable,
std::chrono::milliseconds timeout = std::chrono::milliseconds::max()) {
return WaitAny(wait_handles.data(), wait_handles.size(), is_alertable,
timeout);
}
// Models a Win32-like event object. // Models a Win32-like event object.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
class Event : public WaitHandle { class Event : public WaitHandle {

View File

@ -102,8 +102,8 @@ class Win32Handle : public T {
HANDLE handle_ = nullptr; HANDLE handle_ = nullptr;
}; };
WaitResult WaitHandle::Wait(WaitHandle* wait_handle, bool is_alertable, WaitResult Wait(WaitHandle* wait_handle, bool is_alertable,
std::chrono::milliseconds timeout) { std::chrono::milliseconds timeout) {
HANDLE handle = wait_handle->native_handle(); HANDLE handle = wait_handle->native_handle();
DWORD result = WaitForSingleObjectEx(handle, DWORD(timeout.count()), DWORD result = WaitForSingleObjectEx(handle, DWORD(timeout.count()),
is_alertable ? TRUE : FALSE); is_alertable ? TRUE : FALSE);
@ -122,10 +122,9 @@ WaitResult WaitHandle::Wait(WaitHandle* wait_handle, bool is_alertable,
} }
} }
WaitResult WaitHandle::SignalAndWait(WaitHandle* wait_handle_to_signal, WaitResult SignalAndWait(WaitHandle* wait_handle_to_signal,
WaitHandle* wait_handle_to_wait_on, WaitHandle* wait_handle_to_wait_on, bool is_alertable,
bool is_alertable, std::chrono::milliseconds timeout) {
std::chrono::milliseconds timeout) {
HANDLE handle_to_signal = wait_handle_to_signal->native_handle(); HANDLE handle_to_signal = wait_handle_to_signal->native_handle();
HANDLE handle_to_wait_on = wait_handle_to_wait_on->native_handle(); HANDLE handle_to_wait_on = wait_handle_to_wait_on->native_handle();
DWORD result = DWORD result =
@ -146,9 +145,10 @@ WaitResult WaitHandle::SignalAndWait(WaitHandle* wait_handle_to_signal,
} }
} }
std::pair<WaitResult, size_t> WaitHandle::WaitMultiple( std::pair<WaitResult, size_t> WaitMultiple(WaitHandle* wait_handles[],
WaitHandle* wait_handles[], size_t wait_handle_count, bool wait_all, size_t wait_handle_count,
bool is_alertable, std::chrono::milliseconds timeout) { bool wait_all, bool is_alertable,
std::chrono::milliseconds timeout) {
std::vector<HANDLE> handles(wait_handle_count); std::vector<HANDLE> handles(wait_handle_count);
for (size_t i = 0; i < wait_handle_count; ++i) { for (size_t i = 0; i < wait_handle_count; ++i) {
handles[i] = wait_handles[i]->native_handle(); handles[i] = wait_handles[i]->native_handle();

View File

@ -17,9 +17,9 @@ namespace xe {
namespace kernel { namespace kernel {
typedef struct { typedef struct {
xe::be<DWORD> count; xe::be<uint32_t> count;
xe::be<DWORD> state[5]; xe::be<uint32_t> state[5];
xe::be<BYTE> buffer[64]; uint8_t buffer[64];
} XECRYPT_SHA_STATE; } XECRYPT_SHA_STATE;
void XeCryptShaInit(pointer_t<XECRYPT_SHA_STATE> sha_state) { void XeCryptShaInit(pointer_t<XECRYPT_SHA_STATE> sha_state) {

View File

@ -7,6 +7,7 @@
****************************************************************************** ******************************************************************************
*/ */
#include "xenia/base/debugging.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/objects/xthread.h" #include "xenia/kernel/objects/xthread.h"
@ -17,7 +18,7 @@
namespace xe { namespace xe {
namespace kernel { namespace kernel {
void DbgBreakPoint() { DebugBreak(); } void DbgBreakPoint() { xe::debugging::Break(); }
DECLARE_XBOXKRNL_EXPORT(DbgBreakPoint, ExportTag::kImportant); DECLARE_XBOXKRNL_EXPORT(DbgBreakPoint, ExportTag::kImportant);
// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
@ -79,13 +80,13 @@ void RtlRaiseException(pointer_t<X_EXCEPTION_RECORD> record) {
if (record->exception_code == 0xE06D7363) { if (record->exception_code == 0xE06D7363) {
// C++ exception. // C++ exception.
// http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx // http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
DebugBreak(); xe::debugging::Break();
return; return;
} }
// TODO(benvanik): unwinding. // TODO(benvanik): unwinding.
// This is going to suck. // This is going to suck.
DebugBreak(); xe::debugging::Break();
} }
DECLARE_XBOXKRNL_EXPORT(RtlRaiseException, ExportTag::kImportant); DECLARE_XBOXKRNL_EXPORT(RtlRaiseException, ExportTag::kImportant);
@ -94,7 +95,7 @@ void KeBugCheckEx(dword_t code, dword_t param1, dword_t param2, dword_t param3,
XELOGD("*** STOP: 0x%.8X (0x%.8X, 0x%.8X, 0x%.8X, 0x%.8X)", code, param1, XELOGD("*** STOP: 0x%.8X (0x%.8X, 0x%.8X, 0x%.8X, 0x%.8X)", code, param1,
param2, param3, param4); param2, param3, param4);
fflush(stdout); fflush(stdout);
DebugBreak(); xe::debugging::Break();
assert_always(); assert_always();
} }
DECLARE_XBOXKRNL_EXPORT(KeBugCheckEx, ExportTag::kImportant); DECLARE_XBOXKRNL_EXPORT(KeBugCheckEx, ExportTag::kImportant);

View File

@ -128,7 +128,8 @@ X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
TimeoutTicksToMs(*opt_timeout))) TimeoutTicksToMs(*opt_timeout)))
: std::chrono::milliseconds::max(); : std::chrono::milliseconds::max();
auto result = wait_handle->Wait(alertable ? true : false, timeout_ms); auto result =
xe::threading::Wait(wait_handle, alertable ? true : false, timeout_ms);
switch (result) { switch (result) {
case xe::threading::WaitResult::kSuccess: case xe::threading::WaitResult::kSuccess:
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
@ -136,7 +137,7 @@ X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
// Or X_STATUS_ALERTED? // Or X_STATUS_ALERTED?
return X_STATUS_USER_APC; return X_STATUS_USER_APC;
case xe::threading::WaitResult::kTimeout: case xe::threading::WaitResult::kTimeout:
YieldProcessor(); xe::threading::MaybeYield();
return X_STATUS_TIMEOUT; return X_STATUS_TIMEOUT;
default: default:
case xe::threading::WaitResult::kAbandoned: case xe::threading::WaitResult::kAbandoned:
@ -153,7 +154,7 @@ X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
TimeoutTicksToMs(*opt_timeout))) TimeoutTicksToMs(*opt_timeout)))
: std::chrono::milliseconds::max(); : std::chrono::milliseconds::max();
auto result = xe::threading::WaitHandle::SignalAndWait( auto result = xe::threading::SignalAndWait(
signal_object->GetWaitHandle(), wait_object->GetWaitHandle(), signal_object->GetWaitHandle(), wait_object->GetWaitHandle(),
alertable ? true : false, timeout_ms); alertable ? true : false, timeout_ms);
switch (result) { switch (result) {
@ -163,7 +164,7 @@ X_STATUS XObject::SignalAndWait(XObject* signal_object, XObject* wait_object,
// Or X_STATUS_ALERTED? // Or X_STATUS_ALERTED?
return X_STATUS_USER_APC; return X_STATUS_USER_APC;
case xe::threading::WaitResult::kTimeout: case xe::threading::WaitResult::kTimeout:
YieldProcessor(); xe::threading::MaybeYield();
return X_STATUS_TIMEOUT; return X_STATUS_TIMEOUT;
default: default:
case xe::threading::WaitResult::kAbandoned: case xe::threading::WaitResult::kAbandoned:
@ -188,8 +189,8 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
: std::chrono::milliseconds::max(); : std::chrono::milliseconds::max();
if (wait_type) { if (wait_type) {
auto result = xe::threading::WaitHandle::WaitAny( auto result = xe::threading::WaitAny(std::move(wait_handles),
std::move(wait_handles), alertable ? true : false, timeout_ms); alertable ? true : false, timeout_ms);
switch (result.first) { switch (result.first) {
case xe::threading::WaitResult::kSuccess: case xe::threading::WaitResult::kSuccess:
return X_STATUS(result.second); return X_STATUS(result.second);
@ -197,7 +198,7 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
// Or X_STATUS_ALERTED? // Or X_STATUS_ALERTED?
return X_STATUS_USER_APC; return X_STATUS_USER_APC;
case xe::threading::WaitResult::kTimeout: case xe::threading::WaitResult::kTimeout:
YieldProcessor(); xe::threading::MaybeYield();
return X_STATUS_TIMEOUT; return X_STATUS_TIMEOUT;
default: default:
case xe::threading::WaitResult::kAbandoned: case xe::threading::WaitResult::kAbandoned:
@ -206,8 +207,8 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
return X_STATUS_UNSUCCESSFUL; return X_STATUS_UNSUCCESSFUL;
} }
} else { } else {
auto result = xe::threading::WaitHandle::WaitAll( auto result = xe::threading::WaitAll(std::move(wait_handles),
std::move(wait_handles), alertable ? true : false, timeout_ms); alertable ? true : false, timeout_ms);
switch (result) { switch (result) {
case xe::threading::WaitResult::kSuccess: case xe::threading::WaitResult::kSuccess:
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
@ -215,7 +216,7 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
// Or X_STATUS_ALERTED? // Or X_STATUS_ALERTED?
return X_STATUS_USER_APC; return X_STATUS_USER_APC;
case xe::threading::WaitResult::kTimeout: case xe::threading::WaitResult::kTimeout:
YieldProcessor(); xe::threading::MaybeYield();
return X_STATUS_TIMEOUT; return X_STATUS_TIMEOUT;
default: default:
case xe::threading::WaitResult::kAbandoned: case xe::threading::WaitResult::kAbandoned: