Cleanup some Ke* threading APIs (and update the dispatch header when possible)
This commit is contained in:
parent
dae37b66a3
commit
4301806061
|
@ -17,6 +17,11 @@
|
|||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
// http://www.nirsoft.net/kernel_struct/vista/KEVENT.html
|
||||
struct X_KEVENT {
|
||||
X_DISPATCH_HEADER header;
|
||||
};
|
||||
|
||||
class XEvent : public XObject {
|
||||
public:
|
||||
XEvent(KernelState* kernel_state);
|
||||
|
|
|
@ -20,7 +20,7 @@ XSemaphore::~XSemaphore() = default;
|
|||
void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) {
|
||||
assert_false(semaphore_);
|
||||
|
||||
CreateNative(sizeof(X_SEMAPHORE));
|
||||
CreateNative(sizeof(X_KSEMAPHORE));
|
||||
|
||||
semaphore_ = xe::threading::Semaphore::Create(initial_count, maximum_count);
|
||||
}
|
||||
|
@ -28,8 +28,9 @@ void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) {
|
|||
void XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER& header) {
|
||||
assert_false(semaphore_);
|
||||
|
||||
// NOT IMPLEMENTED
|
||||
// We expect Initialize to be called shortly.
|
||||
auto semaphore = reinterpret_cast<X_KSEMAPHORE*>(native_ptr);
|
||||
semaphore_ = xe::threading::Semaphore::Create(semaphore->header.signal_state,
|
||||
semaphore->limit);
|
||||
}
|
||||
|
||||
int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) {
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
struct X_SEMAPHORE {
|
||||
struct X_KSEMAPHORE {
|
||||
X_DISPATCH_HEADER header;
|
||||
// TODO: Make this not empty!
|
||||
xe::be<uint32_t> limit;
|
||||
};
|
||||
|
||||
class XSemaphore : public XObject {
|
||||
|
|
|
@ -423,6 +423,65 @@ SHIM_CALL KeTlsSetValue_shim(PPCContext* ppc_context,
|
|||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
dword_result_t KeInitializeEvent(pointer_t<X_KEVENT> event_ptr,
|
||||
dword_t event_type, dword_t initial_state) {
|
||||
event_ptr.Zero();
|
||||
event_ptr->header.type = event_type;
|
||||
event_ptr->header.signal_state = (uint32_t)initial_state;
|
||||
auto ev =
|
||||
XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr, event_type);
|
||||
if (!ev) {
|
||||
return X_STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(KeInitializeEvent,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
dword_result_t KeSetEvent(pointer_t<X_KEVENT> event_ptr, dword_t increment,
|
||||
dword_t wait) {
|
||||
// Update dispatch header
|
||||
xe::atomic_exchange(xe::byte_swap<uint32_t>(1),
|
||||
(uint32_t*)&event_ptr->header.signal_state);
|
||||
|
||||
auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr);
|
||||
if (!ev) {
|
||||
assert_always();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ev->Set(increment, !!wait);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(KeSetEvent,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
dword_result_t KePulseEvent(pointer_t<X_KEVENT> event_ptr, dword_t increment,
|
||||
dword_t wait) {
|
||||
auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr);
|
||||
if (!ev) {
|
||||
assert_always();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ev->Pulse(increment, !!wait);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(KePulseEvent, ExportTag::kImplemented);
|
||||
|
||||
dword_result_t KeResetEvent(pointer_t<X_KEVENT> event_ptr) {
|
||||
// Update dispatch header
|
||||
xe::atomic_exchange(0, (uint32_t*)&event_ptr->header.signal_state);
|
||||
|
||||
auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr);
|
||||
if (!ev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ev->Reset();
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(KeResetEvent,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
|
@ -451,43 +510,6 @@ SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context,
|
|||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL KeInitializeEvent_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t event_type = SHIM_GET_ARG_32(1);
|
||||
uint32_t initial_state = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("KeInitializeEvent(%.8X, %.8X, %.8X)", handle_ptr, event_type,
|
||||
initial_state);
|
||||
|
||||
XEvent* ev = new XEvent(kernel_state);
|
||||
ev->Initialize(!event_type, !!initial_state);
|
||||
|
||||
if (handle_ptr) {
|
||||
SHIM_SET_MEM_32(handle_ptr, ev->handle());
|
||||
}
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL KeSetEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||
uint32_t event_ref = SHIM_GET_ARG_32(0);
|
||||
uint32_t increment = SHIM_GET_ARG_32(1);
|
||||
uint32_t wait = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("KeSetEvent(%.8X, %.8X, %.8X)", event_ref, increment, wait);
|
||||
|
||||
void* event_ptr = SHIM_MEM_ADDR(event_ref);
|
||||
|
||||
auto ev = XObject::GetNativeObject<XEvent>(kernel_state, event_ptr);
|
||||
if (!ev) {
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
auto result = ev->Set(increment, !!wait);
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtSetEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||
uint32_t event_handle = SHIM_GET_ARG_32(0);
|
||||
uint32_t previous_state_ptr = SHIM_GET_ARG_32(1);
|
||||
|
@ -509,25 +531,6 @@ SHIM_CALL NtSetEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
|||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL KePulseEvent_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t event_ref = SHIM_GET_ARG_32(0);
|
||||
uint32_t increment = SHIM_GET_ARG_32(1);
|
||||
uint32_t wait = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("KePulseEvent(%.8X, %.8X, %.8X)", event_ref, increment, wait);
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
void* event_ptr = SHIM_MEM_ADDR(event_ref);
|
||||
auto ev = XObject::GetNativeObject<XEvent>(kernel_state, event_ptr);
|
||||
if (ev) {
|
||||
result = ev->Pulse(increment, !!wait);
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtPulseEvent_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t event_handle = SHIM_GET_ARG_32(0);
|
||||
|
@ -550,23 +553,6 @@ SHIM_CALL NtPulseEvent_shim(PPCContext* ppc_context,
|
|||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL KeResetEvent_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t event_ref = SHIM_GET_ARG_32(0);
|
||||
|
||||
XELOGD("KeResetEvent(%.8X)", event_ref);
|
||||
|
||||
void* event_ptr = SHIM_MEM_ADDR(event_ref);
|
||||
auto ev = XObject::GetNativeObject<XEvent>(kernel_state, event_ptr);
|
||||
if (!ev) {
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
auto result = ev->Reset();
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
dword_result_t NtClearEvent(dword_t handle) {
|
||||
X_STATUS result = X_STATUS_SUCCESS;
|
||||
|
||||
|
@ -582,6 +568,41 @@ dword_result_t NtClearEvent(dword_t handle) {
|
|||
DECLARE_XBOXKRNL_EXPORT(NtClearEvent,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff552150(v=vs.85).aspx
|
||||
void KeInitializeSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr, dword_t count,
|
||||
dword_t limit) {
|
||||
semaphore_ptr->header.type = 5; // SemaphoreObject
|
||||
semaphore_ptr->header.signal_state = (uint32_t)count;
|
||||
semaphore_ptr->limit = (uint32_t)limit;
|
||||
|
||||
auto sem = XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr,
|
||||
5 /* SemaphoreObject */);
|
||||
if (!sem) {
|
||||
assert_always();
|
||||
return;
|
||||
}
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(KeInitializeSemaphore,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
dword_result_t KeReleaseSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr,
|
||||
dword_t increment, dword_t adjustment,
|
||||
dword_t wait) {
|
||||
auto sem =
|
||||
XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr);
|
||||
if (!sem) {
|
||||
assert_always();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(benvanik): increment thread priority?
|
||||
// TODO(benvanik): wait?
|
||||
|
||||
return sem->ReleaseSemaphore(adjustment);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(KeReleaseSemaphore,
|
||||
ExportTag::kImplemented | ExportTag::kThreading);
|
||||
|
||||
SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
|
@ -613,48 +634,6 @@ SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context,
|
|||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
SHIM_CALL KeInitializeSemaphore_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t semaphore_ref = SHIM_GET_ARG_32(0);
|
||||
int32_t count = SHIM_GET_ARG_32(1);
|
||||
int32_t limit = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("KeInitializeSemaphore(%.8X, %d, %d)", semaphore_ref, count, limit);
|
||||
|
||||
void* semaphore_ptr = SHIM_MEM_ADDR(semaphore_ref);
|
||||
auto sem = XObject::GetNativeObject<XSemaphore>(kernel_state, semaphore_ptr,
|
||||
5 /* SemaphoreObject */);
|
||||
if (!sem) {
|
||||
return;
|
||||
}
|
||||
|
||||
sem->Initialize(count, limit);
|
||||
}
|
||||
|
||||
SHIM_CALL KeReleaseSemaphore_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t semaphore_ref = SHIM_GET_ARG_32(0);
|
||||
int32_t increment = SHIM_GET_ARG_32(1);
|
||||
int32_t adjustment = SHIM_GET_ARG_32(2);
|
||||
int32_t wait = SHIM_GET_ARG_32(3);
|
||||
|
||||
XELOGD("KeReleaseSemaphore(%.8X, %d, %d, %d)", semaphore_ref, increment,
|
||||
adjustment, wait);
|
||||
|
||||
void* semaphore_ptr = SHIM_MEM_ADDR(semaphore_ref);
|
||||
auto sem = XObject::GetNativeObject<XSemaphore>(kernel_state, semaphore_ptr);
|
||||
if (!sem) {
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(benvanik): increment thread priority?
|
||||
// TODO(benvanik): wait?
|
||||
|
||||
int32_t result = sem->ReleaseSemaphore(adjustment);
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t sem_handle = SHIM_GET_ARG_32(0);
|
||||
|
@ -680,35 +659,30 @@ SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context,
|
|||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
SHIM_CALL NtCreateMutant_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t initial_owner = SHIM_GET_ARG_32(2);
|
||||
|
||||
XELOGD("NtCreateMutant(%.8X, %.8X, %.1X)", handle_ptr, obj_attributes_ptr,
|
||||
initial_owner);
|
||||
|
||||
dword_result_t NtCreateMutant(lpdword_t handle_out,
|
||||
pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes,
|
||||
dword_t initial_owner) {
|
||||
// TODO(benvanik): check for name collision. May return existing object if
|
||||
// type matches.
|
||||
if (obj_attributes_ptr) {
|
||||
AssertNoNameCollision(kernel_state, obj_attributes_ptr);
|
||||
if (obj_attributes) {
|
||||
AssertNoNameCollision(kernel_state(), obj_attributes);
|
||||
}
|
||||
|
||||
XMutant* mutant = new XMutant(kernel_state);
|
||||
XMutant* mutant = new XMutant(kernel_state());
|
||||
mutant->Initialize(initial_owner ? true : false);
|
||||
|
||||
// obj_attributes may have a name inside of it, if != NULL.
|
||||
if (obj_attributes_ptr) {
|
||||
mutant->SetAttributes(obj_attributes_ptr);
|
||||
if (obj_attributes) {
|
||||
mutant->SetAttributes(obj_attributes);
|
||||
}
|
||||
|
||||
if (handle_ptr) {
|
||||
SHIM_SET_MEM_32(handle_ptr, mutant->handle());
|
||||
if (handle_out) {
|
||||
*handle_out = mutant->handle();
|
||||
}
|
||||
|
||||
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT(NtCreateMutant, ExportTag::kImplemented);
|
||||
|
||||
SHIM_CALL NtReleaseMutant_shim(PPCContext* ppc_context,
|
||||
KernelState* kernel_state) {
|
||||
|
@ -1331,6 +1305,7 @@ pointer_result_t InterlockedFlushSList(pointer_t<X_SLIST_HEADER> plist_ptr) {
|
|||
|
||||
uint32_t next = plist_ptr->next.next;
|
||||
plist_ptr->next.next = 0;
|
||||
plist_ptr->depth = 0;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
@ -1365,19 +1340,12 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports(
|
|||
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsSetValue, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtSetEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KePulseEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtPulseEvent, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeResetEvent, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateSemaphore, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeSemaphore, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeReleaseSemaphore, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseSemaphore, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateMutant, state);
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseMutant, state);
|
||||
|
||||
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateTimer, state);
|
||||
|
|
Loading…
Reference in New Issue