mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-10-12 10:28:08 +00:00
[c-host] add spinlock support to events and alter dxgi to use them
This commit is contained in:
@@ -38,6 +38,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
struct AppState
|
||||
{
|
||||
LARGE_INTEGER perfFreq;
|
||||
HINSTANCE hInst;
|
||||
|
||||
int argc;
|
||||
@@ -69,6 +70,15 @@ struct osThreadHandle
|
||||
int resultCode;
|
||||
};
|
||||
|
||||
struct osEventHandle
|
||||
{
|
||||
bool reset;
|
||||
HANDLE handle;
|
||||
bool wrapped;
|
||||
unsigned int msSpinTime;
|
||||
volatile bool signaled;
|
||||
};
|
||||
|
||||
// undocumented API to adjust the system timer resolution (yes, its a nasty hack)
|
||||
typedef NTSTATUS (__stdcall *ZwSetTimerResolution_t)(ULONG RequestedResolution, BOOLEAN Set, PULONG ActualResolution);
|
||||
static ZwSetTimerResolution_t ZwSetTimerResolution = NULL;
|
||||
@@ -320,6 +330,9 @@ bool app_init()
|
||||
DEBUG_INFO("System timer resolution: %.2f ns", (float)actualResolution / 100.0f);
|
||||
}
|
||||
|
||||
// get the performance frequency for spinlocks
|
||||
QueryPerformanceFrequency(&app.perfFreq);
|
||||
|
||||
HDEVINFO deviceInfoSet;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||
@@ -488,36 +501,98 @@ bool os_joinThread(osThreadHandle * handle, int * resultCode)
|
||||
return false;
|
||||
}
|
||||
|
||||
osEventHandle * os_createEvent(bool autoReset)
|
||||
osEventHandle * os_createEvent(bool autoReset, unsigned int msSpinTime)
|
||||
{
|
||||
HANDLE event = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL);
|
||||
osEventHandle * event = (osEventHandle *)malloc(sizeof(osEventHandle));
|
||||
if (!event)
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create the event", GetLastError());
|
||||
DEBUG_ERROR("out of ram");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (osEventHandle*)event;
|
||||
event->reset = autoReset;
|
||||
event->wrapped = false;
|
||||
event->msSpinTime = msSpinTime;
|
||||
event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL);
|
||||
if (!event->handle)
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create the event", GetLastError());
|
||||
free(event);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
osEventHandle * os_wrapEvent(HANDLE event)
|
||||
osEventHandle * os_wrapEvent(HANDLE handle)
|
||||
{
|
||||
return (osEventHandle*)event;
|
||||
osEventHandle * event = (osEventHandle *)malloc(sizeof(osEventHandle));
|
||||
if (!event)
|
||||
{
|
||||
DEBUG_ERROR("out of ram");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event->reset = false;
|
||||
event->handle = event;
|
||||
event->wrapped = true;
|
||||
event->msSpinTime = 0;
|
||||
return event;
|
||||
}
|
||||
|
||||
void os_freeEvent(osEventHandle * handle)
|
||||
void os_freeEvent(osEventHandle * event)
|
||||
{
|
||||
CloseHandle((HANDLE)handle);
|
||||
CloseHandle(event->handle);
|
||||
}
|
||||
|
||||
bool os_waitEvent(osEventHandle * handle, unsigned int timeout)
|
||||
bool os_waitEvent(osEventHandle * event, unsigned int timeout)
|
||||
{
|
||||
// wrapped events can't be enahnced
|
||||
if (!event->wrapped)
|
||||
{
|
||||
if (event->signaled)
|
||||
return true;
|
||||
|
||||
if (timeout == 0)
|
||||
return event->signaled;
|
||||
|
||||
if (event->msSpinTime)
|
||||
{
|
||||
unsigned int spinTime = event->msSpinTime;
|
||||
if (timeout != TIMEOUT_INFINITE)
|
||||
{
|
||||
if (timeout > event->msSpinTime)
|
||||
timeout -= event->msSpinTime;
|
||||
else
|
||||
{
|
||||
spinTime -= timeout;
|
||||
timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
LARGE_INTEGER end, now;
|
||||
QueryPerformanceCounter(&end);
|
||||
end.QuadPart += (app.perfFreq.QuadPart / 1000) * spinTime;
|
||||
while(!event->signaled)
|
||||
{
|
||||
QueryPerformanceCounter(&now);
|
||||
if (now.QuadPart >= end.QuadPart)
|
||||
break;
|
||||
}
|
||||
|
||||
if (event->signaled)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout;
|
||||
while(true)
|
||||
{
|
||||
switch(WaitForSingleObject((HANDLE)handle, to))
|
||||
switch(WaitForSingleObject(event->handle, to))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
if (!event->reset)
|
||||
event->signaled = true;
|
||||
return true;
|
||||
|
||||
case WAIT_ABANDONED:
|
||||
@@ -539,18 +614,24 @@ bool os_waitEvent(osEventHandle * handle, unsigned int timeout)
|
||||
}
|
||||
}
|
||||
|
||||
bool os_waitEvents(osEventHandle * handles[], int count, bool waitAll, unsigned int timeout)
|
||||
bool os_waitEvents(osEventHandle * events[], int count, bool waitAll, unsigned int timeout)
|
||||
{
|
||||
const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout;
|
||||
|
||||
HANDLE * handles = (HANDLE *)malloc(sizeof(HANDLE) * count);
|
||||
for(int i = 0; i < count; ++i)
|
||||
handles[i] = events[i]->handle;
|
||||
|
||||
while(true)
|
||||
{
|
||||
DWORD result = WaitForMultipleObjects(count, (HANDLE*)handles, waitAll, to);
|
||||
DWORD result = WaitForMultipleObjects(count, handles, waitAll, to);
|
||||
if (result >= WAIT_OBJECT_0 && result < count)
|
||||
{
|
||||
// null non signalled events from the handle list
|
||||
// null non signaled events from the handle list
|
||||
for(int i = 0; i < count; ++i)
|
||||
if (i != result && !os_waitEvent(handles[i], 0))
|
||||
if (i != result && !os_waitEvent(events[i], 0))
|
||||
handles[i] = NULL;
|
||||
free(handles);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -563,24 +644,29 @@ bool os_waitEvents(osEventHandle * handles[], int count, bool waitAll, unsigned
|
||||
if (timeout == TIMEOUT_INFINITE)
|
||||
continue;
|
||||
|
||||
free(handles);
|
||||
return false;
|
||||
|
||||
case WAIT_FAILED:
|
||||
DEBUG_WINERROR("Wait for event failed", GetLastError());
|
||||
free(handles);
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_ERROR("Unknown wait event return code");
|
||||
free(handles);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool os_signalEvent(osEventHandle * handle)
|
||||
bool os_signalEvent(osEventHandle * event)
|
||||
{
|
||||
return SetEvent((HANDLE)handle);
|
||||
event->signaled = true;
|
||||
return SetEvent(event->handle);
|
||||
}
|
||||
|
||||
bool os_resetEvent(osEventHandle * handle)
|
||||
bool os_resetEvent(osEventHandle * event)
|
||||
{
|
||||
return ResetEvent((HANDLE)handle);
|
||||
event->signaled = false;
|
||||
return ResetEvent(event->handle);
|
||||
}
|
Reference in New Issue
Block a user