Cleanup some Ke* threading APIs (and update the dispatch header when possible)

This commit is contained in:
Dr. Chat 2015-07-25 11:43:25 -05:00
parent dae37b66a3
commit 4301806061
4 changed files with 118 additions and 144 deletions

View File

@ -17,6 +17,11 @@
namespace xe { namespace xe {
namespace kernel { namespace kernel {
// http://www.nirsoft.net/kernel_struct/vista/KEVENT.html
struct X_KEVENT {
X_DISPATCH_HEADER header;
};
class XEvent : public XObject { class XEvent : public XObject {
public: public:
XEvent(KernelState* kernel_state); XEvent(KernelState* kernel_state);

View File

@ -20,7 +20,7 @@ XSemaphore::~XSemaphore() = default;
void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) { void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) {
assert_false(semaphore_); assert_false(semaphore_);
CreateNative(sizeof(X_SEMAPHORE)); CreateNative(sizeof(X_KSEMAPHORE));
semaphore_ = xe::threading::Semaphore::Create(initial_count, maximum_count); 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) { void XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER& header) {
assert_false(semaphore_); assert_false(semaphore_);
// NOT IMPLEMENTED auto semaphore = reinterpret_cast<X_KSEMAPHORE*>(native_ptr);
// We expect Initialize to be called shortly. semaphore_ = xe::threading::Semaphore::Create(semaphore->header.signal_state,
semaphore->limit);
} }
int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) { int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) {

View File

@ -17,9 +17,9 @@
namespace xe { namespace xe {
namespace kernel { namespace kernel {
struct X_SEMAPHORE { struct X_KSEMAPHORE {
X_DISPATCH_HEADER header; X_DISPATCH_HEADER header;
// TODO: Make this not empty! xe::be<uint32_t> limit;
}; };
class XSemaphore : public XObject { class XSemaphore : public XObject {

View File

@ -423,6 +423,65 @@ SHIM_CALL KeTlsSetValue_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(result); 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, SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context,
KernelState* kernel_state) { KernelState* kernel_state) {
uint32_t handle_ptr = SHIM_GET_ARG_32(0); 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_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) { SHIM_CALL NtSetEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) {
uint32_t event_handle = SHIM_GET_ARG_32(0); uint32_t event_handle = SHIM_GET_ARG_32(0);
uint32_t previous_state_ptr = SHIM_GET_ARG_32(1); 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_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, SHIM_CALL NtPulseEvent_shim(PPCContext* ppc_context,
KernelState* kernel_state) { KernelState* kernel_state) {
uint32_t event_handle = SHIM_GET_ARG_32(0); 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_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) { dword_result_t NtClearEvent(dword_t handle) {
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
@ -582,6 +568,41 @@ dword_result_t NtClearEvent(dword_t handle) {
DECLARE_XBOXKRNL_EXPORT(NtClearEvent, DECLARE_XBOXKRNL_EXPORT(NtClearEvent,
ExportTag::kImplemented | ExportTag::kThreading); 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, SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context,
KernelState* kernel_state) { KernelState* kernel_state) {
uint32_t handle_ptr = SHIM_GET_ARG_32(0); 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_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, SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context,
KernelState* kernel_state) { KernelState* kernel_state) {
uint32_t sem_handle = SHIM_GET_ARG_32(0); 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_SET_RETURN_32(result);
} }
SHIM_CALL NtCreateMutant_shim(PPCContext* ppc_context, dword_result_t NtCreateMutant(lpdword_t handle_out,
KernelState* kernel_state) { pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes,
uint32_t handle_ptr = SHIM_GET_ARG_32(0); dword_t initial_owner) {
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);
// TODO(benvanik): check for name collision. May return existing object if // TODO(benvanik): check for name collision. May return existing object if
// type matches. // type matches.
if (obj_attributes_ptr) { if (obj_attributes) {
AssertNoNameCollision(kernel_state, obj_attributes_ptr); AssertNoNameCollision(kernel_state(), obj_attributes);
} }
XMutant* mutant = new XMutant(kernel_state); XMutant* mutant = new XMutant(kernel_state());
mutant->Initialize(initial_owner ? true : false); mutant->Initialize(initial_owner ? true : false);
// obj_attributes may have a name inside of it, if != NULL. // obj_attributes may have a name inside of it, if != NULL.
if (obj_attributes_ptr) { if (obj_attributes) {
mutant->SetAttributes(obj_attributes_ptr); mutant->SetAttributes(obj_attributes);
} }
if (handle_ptr) { if (handle_out) {
SHIM_SET_MEM_32(handle_ptr, mutant->handle()); *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, SHIM_CALL NtReleaseMutant_shim(PPCContext* ppc_context,
KernelState* kernel_state) { 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; uint32_t next = plist_ptr->next.next;
plist_ptr->next.next = 0; plist_ptr->next.next = 0;
plist_ptr->depth = 0;
return next; return next;
} }
@ -1365,19 +1340,12 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports(
SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsSetValue, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsSetValue, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateEvent, 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", NtSetEvent, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KePulseEvent, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtPulseEvent, 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", 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", NtReleaseSemaphore, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateMutant, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseMutant, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseMutant, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateTimer, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateTimer, state);