Lookup thread/event/etc objects by name on create to try to reuse.

This commit is contained in:
Ben Vanik
2015-09-01 18:09:44 -07:00
parent 3f433fe20a
commit 3c1e012098

View File

@@ -61,14 +61,15 @@ namespace kernel {
// stw r3, 0x160(r11) // stw r3, 0x160(r11)
// } // }
void AssertNoNameCollision(KernelState* kernel_state, template <typename T>
uint32_t obj_attributes_ptr) { object_ref<T> LookupNamedObject(KernelState* kernel_state,
uint32_t obj_attributes_ptr) {
// If the name exists and its type matches, we can return that (ref+1) // If the name exists and its type matches, we can return that (ref+1)
// with a success of NAME_EXISTS. // with a success of NAME_EXISTS.
// If the name exists and its type doesn't match, we do NAME_COLLISION. // If the name exists and its type doesn't match, we do NAME_COLLISION.
// Otherwise, we add like normal. // Otherwise, we add like normal.
if (!obj_attributes_ptr) { if (!obj_attributes_ptr) {
return; return nullptr;
} }
auto name = X_ANSI_STRING::to_string_indirect( auto name = X_ANSI_STRING::to_string_indirect(
kernel_state->memory()->virtual_membase(), obj_attributes_ptr + 4); kernel_state->memory()->virtual_membase(), obj_attributes_ptr + 4);
@@ -77,10 +78,16 @@ void AssertNoNameCollision(KernelState* kernel_state,
X_RESULT result = X_RESULT result =
kernel_state->object_table()->GetObjectByName(name, &handle); kernel_state->object_table()->GetObjectByName(name, &handle);
if (XSUCCEEDED(result)) { if (XSUCCEEDED(result)) {
// Found something! // Found something! It's been retained, so return.
assert_always("Existing names not implemented"); auto obj = kernel_state->object_table()->LookupObject<T>(handle);
if (obj) {
// The caller will do as it likes.
obj->ReleaseHandle();
return obj;
}
} }
} }
return nullptr;
} }
SHIM_CALL ExCreateThread_shim(PPCContext* ppc_context, SHIM_CALL ExCreateThread_shim(PPCContext* ppc_context,
@@ -494,9 +501,21 @@ SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context,
XELOGD("NtCreateEvent(%.8X, %.8X, %d, %d)", handle_ptr, obj_attributes_ptr, XELOGD("NtCreateEvent(%.8X, %.8X, %d, %d)", handle_ptr, obj_attributes_ptr,
event_type, initial_state); event_type, initial_state);
// TODO(benvanik): check for name collision. May return existing object if // Check for an existing timer with the same name.
// type matches. auto existing_object =
AssertNoNameCollision(kernel_state, obj_attributes_ptr); LookupNamedObject<XEvent>(kernel_state, obj_attributes_ptr);
if (existing_object) {
if (existing_object->type() == XObject::kTypeEvent) {
if (handle_ptr) {
existing_object->RetainHandle();
SHIM_SET_MEM_32(handle_ptr, existing_object->handle());
}
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
} else {
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE);
}
return;
}
XEvent* ev = new XEvent(kernel_state); XEvent* ev = new XEvent(kernel_state);
ev->Initialize(!event_type, !!initial_state); ev->Initialize(!event_type, !!initial_state);
@@ -608,10 +627,20 @@ SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context,
XELOGD("NtCreateSemaphore(%.8X, %.8X, %d, %d)", handle_ptr, XELOGD("NtCreateSemaphore(%.8X, %.8X, %d, %d)", handle_ptr,
obj_attributes_ptr, count, limit); obj_attributes_ptr, count, limit);
// TODO(benvanik): check for name collision. May return existing object if // Check for an existing timer with the same name.
// type matches. auto existing_object =
if (obj_attributes_ptr) { LookupNamedObject<XSemaphore>(kernel_state, obj_attributes_ptr);
AssertNoNameCollision(kernel_state, obj_attributes_ptr); if (existing_object) {
if (existing_object->type() == XObject::kTypeSemaphore) {
if (handle_ptr) {
existing_object->RetainHandle();
SHIM_SET_MEM_32(handle_ptr, existing_object->handle());
}
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
} else {
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE);
}
return;
} }
auto sem = object_ref<XSemaphore>(new XSemaphore(kernel_state)); auto sem = object_ref<XSemaphore>(new XSemaphore(kernel_state));
@@ -657,10 +686,19 @@ SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context,
dword_result_t NtCreateMutant(lpdword_t handle_out, dword_result_t NtCreateMutant(lpdword_t handle_out,
pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes, pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes,
dword_t initial_owner) { dword_t initial_owner) {
// TODO(benvanik): check for name collision. May return existing object if // Check for an existing timer with the same name.
// type matches. auto existing_object = LookupNamedObject<XMutant>(
if (obj_attributes) { kernel_state(), obj_attributes.guest_address());
AssertNoNameCollision(kernel_state(), obj_attributes); if (existing_object) {
if (existing_object->type() == XObject::kTypeMutant) {
if (handle_out) {
existing_object->RetainHandle();
*handle_out = existing_object->handle();
}
return X_STATUS_SUCCESS;
} else {
return X_STATUS_INVALID_HANDLE;
}
} }
XMutant* mutant = new XMutant(kernel_state()); XMutant* mutant = new XMutant(kernel_state());
@@ -720,10 +758,20 @@ SHIM_CALL NtCreateTimer_shim(PPCContext* ppc_context,
XELOGD("NtCreateTimer(%.8X, %.8X, %.1X)", handle_ptr, obj_attributes_ptr, XELOGD("NtCreateTimer(%.8X, %.8X, %.1X)", handle_ptr, obj_attributes_ptr,
timer_type); timer_type);
// TODO(benvanik): check for name collision. May return existing object if // Check for an existing timer with the same name.
// type matches. auto existing_object =
if (obj_attributes_ptr) { LookupNamedObject<XTimer>(kernel_state, obj_attributes_ptr);
AssertNoNameCollision(kernel_state, obj_attributes_ptr); if (existing_object) {
if (existing_object->type() == XObject::kTypeTimer) {
if (handle_ptr) {
existing_object->RetainHandle();
SHIM_SET_MEM_32(handle_ptr, existing_object->handle());
}
SHIM_SET_RETURN_32(X_STATUS_SUCCESS);
} else {
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE);
}
return;
} }
XTimer* timer = new XTimer(kernel_state); XTimer* timer = new XTimer(kernel_state);