mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[common/c-host] move agnostic code into common
library
This commit is contained in:
parent
491ffc3576
commit
0c6ff6822d
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -31,24 +31,3 @@ const char * os_getExecutable();
|
|||||||
unsigned int os_shmemSize();
|
unsigned int os_shmemSize();
|
||||||
bool os_shmemMmap(void **ptr);
|
bool os_shmemMmap(void **ptr);
|
||||||
void os_shmemUnmap();
|
void os_shmemUnmap();
|
||||||
|
|
||||||
// os specific thread functions
|
|
||||||
|
|
||||||
typedef struct osThreadHandle osThreadHandle;
|
|
||||||
typedef int (*osThreadFunction)(void * opaque);
|
|
||||||
|
|
||||||
bool os_createThread(const char * name, osThreadFunction function, void * opaque, osThreadHandle ** handle);
|
|
||||||
bool os_joinThread (osThreadHandle * handle, int * resultCode);
|
|
||||||
|
|
||||||
// os specific event functions
|
|
||||||
|
|
||||||
#define TIMEOUT_INFINITE ((unsigned int)~0)
|
|
||||||
|
|
||||||
typedef struct osEventHandle osEventHandle;
|
|
||||||
|
|
||||||
osEventHandle * os_createEvent(bool autoReset, unsigned int msSpinTime);
|
|
||||||
void os_freeEvent (osEventHandle * handle);
|
|
||||||
bool os_waitEvent (osEventHandle * handle, unsigned int timeout);
|
|
||||||
bool os_waitEvents (osEventHandle * handles[], int count, bool waitAll, unsigned int timeout);
|
|
||||||
bool os_signalEvent(osEventHandle * handle);
|
|
||||||
bool os_resetEvent (osEventHandle * handle);
|
|
@ -7,7 +7,6 @@ include_directories(
|
|||||||
|
|
||||||
add_library(platform_Windows STATIC
|
add_library(platform_Windows STATIC
|
||||||
src/platform.c
|
src/platform.c
|
||||||
src/windebug.c
|
|
||||||
src/mousehook.c
|
src/mousehook.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,10 +20,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "interface/capture.h"
|
#include "interface/capture.h"
|
||||||
#include "interface/platform.h"
|
#include "interface/platform.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/windebug.h"
|
||||||
#include "common/option.h"
|
#include "common/option.h"
|
||||||
#include "common/locking.h"
|
#include "common/locking.h"
|
||||||
#include "windows/debug.h"
|
#include "common/event.h"
|
||||||
#include "windows/platform.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
@ -83,8 +83,8 @@ struct iface
|
|||||||
int texWIndex;
|
int texWIndex;
|
||||||
volatile int texReady;
|
volatile int texReady;
|
||||||
bool needsRelease;
|
bool needsRelease;
|
||||||
osEventHandle * pointerEvent;
|
LGEvent * pointerEvent;
|
||||||
osEventHandle * frameEvent;
|
LGEvent * frameEvent;
|
||||||
|
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
@ -165,7 +165,7 @@ static bool dxgi_create()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->pointerEvent = os_createEvent(true, 10);
|
this->pointerEvent = lgCreateEvent(true, 10);
|
||||||
if (!this->pointerEvent)
|
if (!this->pointerEvent)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("failed to create the pointer event");
|
DEBUG_ERROR("failed to create the pointer event");
|
||||||
@ -173,7 +173,7 @@ static bool dxgi_create()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->frameEvent = os_createEvent(true, 17); // 60Hz = 16.7ms
|
this->frameEvent = lgCreateEvent(true, 17); // 60Hz = 16.7ms
|
||||||
if (!this->frameEvent)
|
if (!this->frameEvent)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("failed to create the frame event");
|
DEBUG_ERROR("failed to create the frame event");
|
||||||
@ -222,8 +222,8 @@ static bool dxgi_init(void * pointerShape, const unsigned int pointerSize)
|
|||||||
this->texWIndex = 0;
|
this->texWIndex = 0;
|
||||||
this->texReady = 0;
|
this->texReady = 0;
|
||||||
|
|
||||||
os_resetEvent(this->frameEvent );
|
lgResetEvent(this->frameEvent );
|
||||||
os_resetEvent(this->pointerEvent);
|
lgResetEvent(this->pointerEvent);
|
||||||
|
|
||||||
status = CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&this->factory);
|
status = CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&this->factory);
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
@ -520,7 +520,7 @@ fail:
|
|||||||
static void dxgi_stop()
|
static void dxgi_stop()
|
||||||
{
|
{
|
||||||
this->stop = true;
|
this->stop = true;
|
||||||
os_signalEvent(this->pointerEvent);
|
lgSignalEvent(this->pointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dxgi_deinit()
|
static bool dxgi_deinit()
|
||||||
@ -598,7 +598,7 @@ static void dxgi_free()
|
|||||||
if (this->initialized)
|
if (this->initialized)
|
||||||
dxgi_deinit();
|
dxgi_deinit();
|
||||||
|
|
||||||
os_freeEvent(this->pointerEvent);
|
lgFreeEvent(this->pointerEvent);
|
||||||
free(this->texture);
|
free(this->texture);
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
@ -683,7 +683,7 @@ static CaptureResult dxgi_capture()
|
|||||||
// set the state, and signal
|
// set the state, and signal
|
||||||
tex->state = TEXTURE_STATE_PENDING_MAP;
|
tex->state = TEXTURE_STATE_PENDING_MAP;
|
||||||
INTERLOCKED_INC(&this->texReady);
|
INTERLOCKED_INC(&this->texReady);
|
||||||
os_signalEvent(this->frameEvent);
|
lgSignalEvent(this->frameEvent);
|
||||||
|
|
||||||
// advance the write index
|
// advance the write index
|
||||||
if (++this->texWIndex == this->maxTextures)
|
if (++this->texWIndex == this->maxTextures)
|
||||||
@ -749,7 +749,7 @@ static CaptureResult dxgi_capture()
|
|||||||
|
|
||||||
// signal about the pointer update
|
// signal about the pointer update
|
||||||
if (signalPointer)
|
if (signalPointer)
|
||||||
os_signalEvent(this->pointerEvent);
|
lgSignalEvent(this->pointerEvent);
|
||||||
|
|
||||||
return CAPTURE_RESULT_OK;
|
return CAPTURE_RESULT_OK;
|
||||||
}
|
}
|
||||||
@ -762,7 +762,7 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame)
|
|||||||
// NOTE: the event may be signaled when there are no frames available
|
// NOTE: the event may be signaled when there are no frames available
|
||||||
if(this->texReady == 0)
|
if(this->texReady == 0)
|
||||||
{
|
{
|
||||||
if (!os_waitEvent(this->frameEvent, 1000))
|
if (!lgWaitEvent(this->frameEvent, 1000))
|
||||||
return CAPTURE_RESULT_TIMEOUT;
|
return CAPTURE_RESULT_TIMEOUT;
|
||||||
|
|
||||||
if (this->texReady == 0)
|
if (this->texReady == 0)
|
||||||
@ -817,7 +817,7 @@ static CaptureResult dxgi_getPointer(CapturePointer * pointer)
|
|||||||
assert(this);
|
assert(this);
|
||||||
assert(this->initialized);
|
assert(this->initialized);
|
||||||
|
|
||||||
if (!os_waitEvent(this->pointerEvent, 1000))
|
if (!lgWaitEvent(this->pointerEvent, 1000))
|
||||||
return CAPTURE_RESULT_TIMEOUT;
|
return CAPTURE_RESULT_TIMEOUT;
|
||||||
|
|
||||||
if (this->stop)
|
if (this->stop)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -19,11 +19,11 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "interface/capture.h"
|
#include "interface/capture.h"
|
||||||
#include "interface/platform.h"
|
#include "interface/platform.h"
|
||||||
#include "windows/platform.h"
|
#include "common/windebug.h"
|
||||||
#include "windows/debug.h"
|
|
||||||
#include "windows/mousehook.h"
|
#include "windows/mousehook.h"
|
||||||
#include "common/option.h"
|
#include "common/option.h"
|
||||||
#include "common/framebuffer.h"
|
#include "common/framebuffer.h"
|
||||||
|
#include "common/event.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -46,8 +46,8 @@ struct iface
|
|||||||
|
|
||||||
NvFBCFrameGrabInfo grabInfo;
|
NvFBCFrameGrabInfo grabInfo;
|
||||||
|
|
||||||
osEventHandle * frameEvent;
|
LGEvent * frameEvent;
|
||||||
osEventHandle * cursorEvents[2];
|
LGEvent * cursorEvents[2];
|
||||||
|
|
||||||
int mouseX, mouseY, mouseHotX, mouseHotY;
|
int mouseX, mouseY, mouseHotX, mouseHotY;
|
||||||
bool mouseVisible;
|
bool mouseVisible;
|
||||||
@ -75,7 +75,7 @@ static void on_mouseMove(int x, int y)
|
|||||||
{
|
{
|
||||||
this->mouseX = x;
|
this->mouseX = x;
|
||||||
this->mouseY = y;
|
this->mouseY = y;
|
||||||
os_signalEvent(this->cursorEvents[0]);
|
lgSignalEvent(this->cursorEvents[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * nvfbc_getName()
|
static const char * nvfbc_getName()
|
||||||
@ -135,7 +135,7 @@ static bool nvfbc_create()
|
|||||||
}
|
}
|
||||||
free(privData);
|
free(privData);
|
||||||
|
|
||||||
this->frameEvent = os_createEvent(true, 17);
|
this->frameEvent = lgCreateEvent(true, 17);
|
||||||
if (!this->frameEvent)
|
if (!this->frameEvent)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("failed to create the frame event");
|
DEBUG_ERROR("failed to create the frame event");
|
||||||
@ -155,7 +155,7 @@ static bool nvfbc_init(void * pointerShape, const unsigned int pointerSize)
|
|||||||
this->pointerSize = pointerSize;
|
this->pointerSize = pointerSize;
|
||||||
|
|
||||||
getDesktopSize(&this->width, &this->height);
|
getDesktopSize(&this->width, &this->height);
|
||||||
os_resetEvent(this->frameEvent);
|
lgResetEvent(this->frameEvent);
|
||||||
|
|
||||||
|
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
@ -174,11 +174,11 @@ static bool nvfbc_init(void * pointerShape, const unsigned int pointerSize)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->cursorEvents[0] = os_createEvent(true, 10);
|
this->cursorEvents[0] = lgCreateEvent(true, 10);
|
||||||
mouseHook_install(on_mouseMove);
|
mouseHook_install(on_mouseMove);
|
||||||
|
|
||||||
if (this->seperateCursor)
|
if (this->seperateCursor)
|
||||||
this->cursorEvents[1] = os_wrapEvent(event);
|
this->cursorEvents[1] = lgWrapEvent(event);
|
||||||
|
|
||||||
DEBUG_INFO("Cursor mode : %s", this->seperateCursor ? "decoupled" : "integrated");
|
DEBUG_INFO("Cursor mode : %s", this->seperateCursor ? "decoupled" : "integrated");
|
||||||
|
|
||||||
@ -189,8 +189,8 @@ static bool nvfbc_init(void * pointerShape, const unsigned int pointerSize)
|
|||||||
static void nvfbc_stop()
|
static void nvfbc_stop()
|
||||||
{
|
{
|
||||||
this->stop = true;
|
this->stop = true;
|
||||||
os_signalEvent(this->cursorEvents[0]);
|
lgSignalEvent(this->cursorEvents[0]);
|
||||||
os_signalEvent(this->frameEvent);
|
lgSignalEvent(this->frameEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nvfbc_deinit()
|
static bool nvfbc_deinit()
|
||||||
@ -204,7 +204,7 @@ static void nvfbc_free()
|
|||||||
NvFBCToSysRelease(&this->nvfbc);
|
NvFBCToSysRelease(&this->nvfbc);
|
||||||
|
|
||||||
if (this->frameEvent)
|
if (this->frameEvent)
|
||||||
os_freeEvent(this->frameEvent);
|
lgFreeEvent(this->frameEvent);
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
this = NULL;
|
this = NULL;
|
||||||
@ -233,13 +233,13 @@ static CaptureResult nvfbc_capture()
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
memcpy(&this->grabInfo, &grabInfo, sizeof(grabInfo));
|
memcpy(&this->grabInfo, &grabInfo, sizeof(grabInfo));
|
||||||
os_signalEvent(this->frameEvent);
|
lgSignalEvent(this->frameEvent);
|
||||||
return CAPTURE_RESULT_OK;
|
return CAPTURE_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CaptureResult nvfbc_waitFrame(CaptureFrame * frame)
|
static CaptureResult nvfbc_waitFrame(CaptureFrame * frame)
|
||||||
{
|
{
|
||||||
if (!os_waitEvent(this->frameEvent, 1000))
|
if (!lgWaitEvent(this->frameEvent, 1000))
|
||||||
return CAPTURE_RESULT_TIMEOUT;
|
return CAPTURE_RESULT_TIMEOUT;
|
||||||
|
|
||||||
if (this->stop)
|
if (this->stop)
|
||||||
@ -282,9 +282,9 @@ static CaptureResult nvfbc_getFrame(FrameBuffer frame)
|
|||||||
|
|
||||||
static CaptureResult nvfbc_getPointer(CapturePointer * pointer)
|
static CaptureResult nvfbc_getPointer(CapturePointer * pointer)
|
||||||
{
|
{
|
||||||
osEventHandle * events[2];
|
LGEvent * events[2];
|
||||||
memcpy(&events, &this->cursorEvents, sizeof(osEventHandle *) * 2);
|
memcpy(&events, &this->cursorEvents, sizeof(LGEvent *) * 2);
|
||||||
if (!os_waitEvents(events, this->seperateCursor ? 2 : 1, false, 1000))
|
if (!lgWaitEvents(events, this->seperateCursor ? 2 : 1, false, 1000))
|
||||||
return CAPTURE_RESULT_TIMEOUT;
|
return CAPTURE_RESULT_TIMEOUT;
|
||||||
|
|
||||||
if (this->stop)
|
if (this->stop)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -18,7 +18,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wrapper.h"
|
#include "wrapper.h"
|
||||||
#include "windows/debug.h"
|
#include "common/windebug.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <NvFBC/nvFBCToSys.h>
|
#include <NvFBC/nvFBCToSys.h>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "windows/mousehook.h"
|
#include "windows/mousehook.h"
|
||||||
#include "windows/debug.h"
|
#include "common/windebug.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -18,7 +18,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "windows/platform.h"
|
|
||||||
#include "windows/mousehook.h"
|
#include "windows/mousehook.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -29,9 +28,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "interface/platform.h"
|
#include "interface/platform.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/windebug.h"
|
||||||
#include "common/option.h"
|
#include "common/option.h"
|
||||||
#include "common/locking.h"
|
#include "common/locking.h"
|
||||||
#include "windows/debug.h"
|
#include "common/thread.h"
|
||||||
#include "ivshmem.h"
|
#include "ivshmem.h"
|
||||||
|
|
||||||
#define ID_MENU_OPEN_LOG 3000
|
#define ID_MENU_OPEN_LOG 3000
|
||||||
@ -60,27 +60,6 @@ static struct AppState app =
|
|||||||
.shmemMap = {0}
|
.shmemMap = {0}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct osThreadHandle
|
|
||||||
{
|
|
||||||
const char * name;
|
|
||||||
osThreadFunction function;
|
|
||||||
void * opaque;
|
|
||||||
HANDLE handle;
|
|
||||||
DWORD threadID;
|
|
||||||
|
|
||||||
int resultCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct osEventHandle
|
|
||||||
{
|
|
||||||
volatile int lock;
|
|
||||||
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)
|
// undocumented API to adjust the system timer resolution (yes, its a nasty hack)
|
||||||
typedef NTSTATUS (__stdcall *ZwSetTimerResolution_t)(ULONG RequestedResolution, BOOLEAN Set, PULONG ActualResolution);
|
typedef NTSTATUS (__stdcall *ZwSetTimerResolution_t)(ULONG RequestedResolution, BOOLEAN Set, PULONG ActualResolution);
|
||||||
static ZwSetTimerResolution_t ZwSetTimerResolution = NULL;
|
static ZwSetTimerResolution_t ZwSetTimerResolution = NULL;
|
||||||
@ -261,8 +240,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
AppendMenu(app.trayMenu, MF_STRING , ID_MENU_EXIT , "Exit" );
|
AppendMenu(app.trayMenu, MF_STRING , ID_MENU_EXIT , "Exit" );
|
||||||
|
|
||||||
// create the application thread
|
// create the application thread
|
||||||
osThreadHandle * thread;
|
LGThread * thread;
|
||||||
if (!os_createThread("appThread", appThread, NULL, &thread))
|
if (!lgCreateThread("appThread", appThread, NULL, &thread))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the main application thread");
|
DEBUG_ERROR("Failed to create the main application thread");
|
||||||
result = -1;
|
result = -1;
|
||||||
@ -292,7 +271,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
shutdown:
|
shutdown:
|
||||||
DestroyMenu(app.trayMenu);
|
DestroyMenu(app.trayMenu);
|
||||||
app_quit();
|
app_quit();
|
||||||
if (!os_joinThread(thread, &result))
|
if (!lgJoinThread(thread, &result))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to join the main application thread");
|
DEBUG_ERROR("Failed to join the main application thread");
|
||||||
result = -1;
|
result = -1;
|
||||||
@ -444,249 +423,4 @@ void os_shmemUnmap()
|
|||||||
DEBUG_WINERROR("DeviceIoControl failed", GetLastError());
|
DEBUG_WINERROR("DeviceIoControl failed", GetLastError());
|
||||||
else
|
else
|
||||||
app.shmemOwned = false;
|
app.shmemOwned = false;
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD WINAPI threadWrapper(LPVOID lpParameter)
|
|
||||||
{
|
|
||||||
osThreadHandle * handle = (osThreadHandle *)lpParameter;
|
|
||||||
handle->resultCode = handle->function(handle->opaque);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool os_createThread(const char * name, osThreadFunction function, void * opaque, osThreadHandle ** handle)
|
|
||||||
{
|
|
||||||
*handle = (osThreadHandle *)malloc(sizeof(osThreadHandle));
|
|
||||||
(*handle)->name = name;
|
|
||||||
(*handle)->function = function;
|
|
||||||
(*handle)->opaque = opaque;
|
|
||||||
(*handle)->handle = CreateThread(NULL, 0, threadWrapper, *handle, 0, &(*handle)->threadID);
|
|
||||||
|
|
||||||
if (!(*handle)->handle)
|
|
||||||
{
|
|
||||||
free(*handle);
|
|
||||||
*handle = NULL;
|
|
||||||
DEBUG_WINERROR("CreateThread failed", GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool os_joinThread(osThreadHandle * handle, int * resultCode)
|
|
||||||
{
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
switch(WaitForSingleObject(handle->handle, INFINITE))
|
|
||||||
{
|
|
||||||
case WAIT_OBJECT_0:
|
|
||||||
if (resultCode)
|
|
||||||
*resultCode = handle->resultCode;
|
|
||||||
CloseHandle(handle->handle);
|
|
||||||
free(handle);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case WAIT_ABANDONED:
|
|
||||||
case WAIT_TIMEOUT:
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case WAIT_FAILED:
|
|
||||||
DEBUG_WINERROR("Wait for thread failed", GetLastError());
|
|
||||||
CloseHandle(handle->handle);
|
|
||||||
free(handle);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_WINERROR("Unknown failure waiting for thread", GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
osEventHandle * os_createEvent(bool autoReset, unsigned int msSpinTime)
|
|
||||||
{
|
|
||||||
osEventHandle * event = (osEventHandle *)malloc(sizeof(osEventHandle));
|
|
||||||
if (!event)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("out of ram");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
event->lock = 0;
|
|
||||||
event->reset = autoReset;
|
|
||||||
event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL);
|
|
||||||
event->wrapped = false;
|
|
||||||
event->msSpinTime = msSpinTime;
|
|
||||||
event->signaled = false;
|
|
||||||
|
|
||||||
if (!event->handle)
|
|
||||||
{
|
|
||||||
DEBUG_WINERROR("Failed to create the event", GetLastError());
|
|
||||||
free(event);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
osEventHandle * os_wrapEvent(HANDLE handle)
|
|
||||||
{
|
|
||||||
osEventHandle * event = (osEventHandle *)malloc(sizeof(osEventHandle));
|
|
||||||
if (!event)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("out of ram");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
event->lock = 0;
|
|
||||||
event->reset = false;
|
|
||||||
event->handle = handle;
|
|
||||||
event->wrapped = true;
|
|
||||||
event->msSpinTime = 0;
|
|
||||||
event->signaled = false;
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void os_freeEvent(osEventHandle * event)
|
|
||||||
{
|
|
||||||
CloseHandle(event->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool os_waitEvent(osEventHandle * event, unsigned int timeout)
|
|
||||||
{
|
|
||||||
// wrapped events can't be enahnced
|
|
||||||
if (!event->wrapped)
|
|
||||||
{
|
|
||||||
if (event->signaled)
|
|
||||||
{
|
|
||||||
if (event->reset)
|
|
||||||
event->signaled = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
bool ret = event->signaled;
|
|
||||||
if (event->reset)
|
|
||||||
event->signaled = false;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (event->reset)
|
|
||||||
event->signaled = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout;
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
switch(WaitForSingleObject(event->handle, to))
|
|
||||||
{
|
|
||||||
case WAIT_OBJECT_0:
|
|
||||||
if (!event->reset)
|
|
||||||
event->signaled = true;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case WAIT_ABANDONED:
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case WAIT_TIMEOUT:
|
|
||||||
if (timeout == TIMEOUT_INFINITE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case WAIT_FAILED:
|
|
||||||
DEBUG_WINERROR("Wait for event failed", GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_ERROR("Unknown wait event return code");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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, handles, waitAll, to);
|
|
||||||
if (result >= WAIT_OBJECT_0 && result < count)
|
|
||||||
{
|
|
||||||
// null non signaled events from the handle list
|
|
||||||
for(int i = 0; i < count; ++i)
|
|
||||||
if (i != result && !os_waitEvent(events[i], 0))
|
|
||||||
handles[i] = NULL;
|
|
||||||
free(handles);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result >= WAIT_ABANDONED_0 && result - WAIT_ABANDONED_0 < count)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch(result)
|
|
||||||
{
|
|
||||||
case WAIT_TIMEOUT:
|
|
||||||
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 * event)
|
|
||||||
{
|
|
||||||
event->signaled = true;
|
|
||||||
return SetEvent(event->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool os_resetEvent(osEventHandle * event)
|
|
||||||
{
|
|
||||||
event->signaled = false;
|
|
||||||
return ResetEvent(event->handle);
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -25,6 +25,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "common/locking.h"
|
#include "common/locking.h"
|
||||||
#include "common/KVMFR.h"
|
#include "common/KVMFR.h"
|
||||||
#include "common/crash.h"
|
#include "common/crash.h"
|
||||||
|
#include "common/thread.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@ -52,10 +53,10 @@ struct app
|
|||||||
FrameBuffer frame[MAX_FRAMES];
|
FrameBuffer frame[MAX_FRAMES];
|
||||||
unsigned int frameOffset[MAX_FRAMES];
|
unsigned int frameOffset[MAX_FRAMES];
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
bool reinit;
|
bool reinit;
|
||||||
osThreadHandle * pointerThread;
|
LGThread * pointerThread;
|
||||||
osThreadHandle * frameThread;
|
LGThread * frameThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct app app;
|
static struct app app;
|
||||||
@ -244,13 +245,13 @@ static int frameThread(void * opaque)
|
|||||||
bool startThreads()
|
bool startThreads()
|
||||||
{
|
{
|
||||||
app.running = true;
|
app.running = true;
|
||||||
if (!os_createThread("CursorThread", pointerThread, NULL, &app.pointerThread))
|
if (!lgCreateThread("CursorThread", pointerThread, NULL, &app.pointerThread))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the pointer thread");
|
DEBUG_ERROR("Failed to create the pointer thread");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!os_createThread("FrameThread", frameThread, NULL, &app.frameThread))
|
if (!lgCreateThread("FrameThread", frameThread, NULL, &app.frameThread))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the frame thread");
|
DEBUG_ERROR("Failed to create the frame thread");
|
||||||
return false;
|
return false;
|
||||||
@ -266,14 +267,14 @@ bool stopThreads()
|
|||||||
app.running = false;
|
app.running = false;
|
||||||
app.iface->stop();
|
app.iface->stop();
|
||||||
|
|
||||||
if (app.frameThread && !os_joinThread(app.frameThread, NULL))
|
if (app.frameThread && !lgJoinThread(app.frameThread, NULL))
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Failed to join the frame thread");
|
DEBUG_WARN("Failed to join the frame thread");
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
app.frameThread = NULL;
|
app.frameThread = NULL;
|
||||||
|
|
||||||
if (app.pointerThread && !os_joinThread(app.pointerThread, NULL))
|
if (app.pointerThread && !lgJoinThread(app.pointerThread, NULL))
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Failed to join the pointer thread");
|
DEBUG_WARN("Failed to join the pointer thread");
|
||||||
ok = false;
|
ok = false;
|
||||||
|
@ -9,6 +9,8 @@ if(ENABLE_BACKTRACE)
|
|||||||
add_definitions(-DENABLE_BACKTRACE)
|
add_definitions(-DENABLE_BACKTRACE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(src/platform)
|
||||||
|
|
||||||
set(COMMON_SOURCES
|
set(COMMON_SOURCES
|
||||||
src/stringutils.c
|
src/stringutils.c
|
||||||
src/stringlist.c
|
src/stringlist.c
|
||||||
@ -16,26 +18,8 @@ set(COMMON_SOURCES
|
|||||||
src/framebuffer.c
|
src/framebuffer.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LINUX_SOURCES
|
add_library(lg_common STATIC ${COMMON_SOURCES})
|
||||||
src/crash.linux.c
|
target_link_libraries(lg_common lg_common_platform)
|
||||||
src/sysinfo.linux.c
|
|
||||||
)
|
|
||||||
|
|
||||||
set(WINDOWS_SOURCES
|
|
||||||
src/crash.windows.c
|
|
||||||
src/sysinfo.windows.c
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
set(SOURCES ${COMMON_SOURCES} ${WINDOWS_SOURCES})
|
|
||||||
add_library(lg_common STATIC ${SOURCES})
|
|
||||||
else()
|
|
||||||
set(SOURCES ${COMMON_SOURCES} ${LINUX_SOURCES})
|
|
||||||
add_library(lg_common STATIC ${SOURCES})
|
|
||||||
if(ENABLE_BACKTRACE)
|
|
||||||
target_link_libraries(lg_common bfd)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_include_directories(lg_common
|
target_include_directories(lg_common
|
||||||
INTERFACE
|
INTERFACE
|
||||||
|
37
common/include/common/event.h
Normal file
37
common/include/common/event.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define TIMEOUT_INFINITE ((unsigned int)~0)
|
||||||
|
|
||||||
|
typedef struct LGEvent LGEvent;
|
||||||
|
|
||||||
|
LGEvent * lgCreateEvent(bool autoReset, unsigned int msSpinTime);
|
||||||
|
void lgFreeEvent (LGEvent * handle);
|
||||||
|
bool lgWaitEvent (LGEvent * handle, unsigned int timeout);
|
||||||
|
bool lgWaitEvents (LGEvent * handles[], int count, bool waitAll, unsigned int timeout);
|
||||||
|
bool lgSignalEvent(LGEvent * handle);
|
||||||
|
bool lgResetEvent (LGEvent * handle);
|
||||||
|
|
||||||
|
// os specific method to wrap/convert a native event into a LGEvent
|
||||||
|
// for windows this is an event HANDLE
|
||||||
|
LGEvent * lgWrapEvent(void * handle);
|
@ -18,7 +18,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(__GCC__) || defined(__GNUC__)
|
|
||||||
#define INTERLOCKED_AND8 __sync_fetch_and_and
|
#define INTERLOCKED_AND8 __sync_fetch_and_and
|
||||||
#define INTERLOCKED_OR8 __sync_fetch_and_or
|
#define INTERLOCKED_OR8 __sync_fetch_and_or
|
||||||
#define INTERLOCKED_INC(x) __sync_fetch_and_add((x), 1)
|
#define INTERLOCKED_INC(x) __sync_fetch_and_add((x), 1)
|
||||||
@ -30,12 +29,3 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
while(__sync_lock_test_and_set(&(lock), 1)) while((lock)); \
|
while(__sync_lock_test_and_set(&(lock), 1)) while((lock)); \
|
||||||
x\
|
x\
|
||||||
__sync_lock_release(&(lock));
|
__sync_lock_release(&(lock));
|
||||||
|
|
||||||
#else
|
|
||||||
#define INTERLOCKED_OR8 InterlockedOr8
|
|
||||||
#define INTERLOCKED_AND8 InterlockedAnd8
|
|
||||||
#define INTERLOCKED_INC InterlockedIncrement
|
|
||||||
#define INTERLOCKED_DEC InterlockedDecrement
|
|
||||||
#define INTERLOCKED_GET(x) InterlockedAdd((x), 0)
|
|
||||||
#define INTERLOCKED_CE(x, c, v) InterlockedCompareExchange((x), (v), (c))
|
|
||||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,7 +17,12 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "interface/platform.h"
|
#pragma once
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
osEventHandle * os_wrapEvent(HANDLE event);
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct LGThread LGThread;
|
||||||
|
typedef int (*LGThreadFunction)(void * opaque);
|
||||||
|
|
||||||
|
bool lgCreateThread(const char * name, LGThreadFunction function, void * opaque, LGThread ** handle);
|
||||||
|
bool lgJoinThread (LGThread * handle, int * resultCode);
|
45
common/include/common/time.h
Normal file
45
common/include/common/time.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline uint64_t getMicrotime()
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
static LARGE_INTEGER freq = { 0 };
|
||||||
|
if (!freq.QuadPart)
|
||||||
|
QueryPerformanceFrequency(&freq);
|
||||||
|
|
||||||
|
LARGE_INTEGER time;
|
||||||
|
QueryPerformanceCounter(&time);
|
||||||
|
return time.QuadPart / (freq.QuadPart / 1000000LL);
|
||||||
|
#else
|
||||||
|
struct timespec time;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||||
|
return (uint64_t)time.tv_sec * 1000000LL + time.tv_nsec / 1000LL;
|
||||||
|
#endif
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -19,7 +19,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "debug.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
11
common/src/platform/CMakeLists.txt
Normal file
11
common/src/platform/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(lg_common_platform LANGUAGES C)
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
add_subdirectory("linux")
|
||||||
|
elseif(WIN32)
|
||||||
|
add_subdirectory("windows")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(lg_common_platform INTERFACE)
|
||||||
|
target_link_libraries(lg_common_platform INTERFACE lg_common_platform_code)
|
11
common/src/platform/linux/CMakeLists.txt
Normal file
11
common/src/platform/linux/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(lg_common_platform_code LANGUAGES C)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${PROJECT_SOURCE_DIR}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(lg_common_platform_code STATIC
|
||||||
|
crash.c
|
||||||
|
sysinfo.c
|
||||||
|
)
|
14
common/src/platform/windows/CMakeLists.txt
Normal file
14
common/src/platform/windows/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(lg_common_platform_code LANGUAGES C)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${PROJECT_SOURCE_DIR}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(lg_common_platform_code STATIC
|
||||||
|
crash.c
|
||||||
|
sysinfo.c
|
||||||
|
thread.c
|
||||||
|
event.c
|
||||||
|
windebug.c
|
||||||
|
)
|
221
common/src/platform/windows/event.c
Normal file
221
common/src/platform/windows/event.c
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/event.h"
|
||||||
|
#include "common/windebug.h"
|
||||||
|
#include "common/time.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
struct LGEvent
|
||||||
|
{
|
||||||
|
volatile int lock;
|
||||||
|
bool reset;
|
||||||
|
HANDLE handle;
|
||||||
|
bool wrapped;
|
||||||
|
unsigned int msSpinTime;
|
||||||
|
volatile bool signaled;
|
||||||
|
};
|
||||||
|
|
||||||
|
LGEvent * lgCreateEvent(bool autoReset, unsigned int msSpinTime)
|
||||||
|
{
|
||||||
|
LGEvent * event = (LGEvent *)malloc(sizeof(LGEvent));
|
||||||
|
if (!event)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("out of ram");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->lock = 0;
|
||||||
|
event->reset = autoReset;
|
||||||
|
event->handle = CreateEvent(NULL, autoReset ? FALSE : TRUE, FALSE, NULL);
|
||||||
|
event->wrapped = false;
|
||||||
|
event->msSpinTime = msSpinTime;
|
||||||
|
event->signaled = false;
|
||||||
|
|
||||||
|
if (!event->handle)
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create the event", GetLastError());
|
||||||
|
free(event);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
LGEvent * lgWrapEvent(void * handle)
|
||||||
|
{
|
||||||
|
LGEvent * event = (LGEvent *)malloc(sizeof(LGEvent));
|
||||||
|
if (!event)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("out of ram");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->lock = 0;
|
||||||
|
event->reset = false;
|
||||||
|
event->handle = (HANDLE)handle;
|
||||||
|
event->wrapped = true;
|
||||||
|
event->msSpinTime = 0;
|
||||||
|
event->signaled = false;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lgFreeEvent(LGEvent * event)
|
||||||
|
{
|
||||||
|
CloseHandle(event->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lgWaitEvent(LGEvent * event, unsigned int timeout)
|
||||||
|
{
|
||||||
|
// wrapped events can't be enahnced
|
||||||
|
if (!event->wrapped)
|
||||||
|
{
|
||||||
|
if (event->signaled)
|
||||||
|
{
|
||||||
|
if (event->reset)
|
||||||
|
event->signaled = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == 0)
|
||||||
|
{
|
||||||
|
bool ret = event->signaled;
|
||||||
|
if (event->reset)
|
||||||
|
event->signaled = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->msSpinTime)
|
||||||
|
{
|
||||||
|
unsigned int spinTime = event->msSpinTime;
|
||||||
|
if (timeout != TIMEOUT_INFINITE)
|
||||||
|
{
|
||||||
|
if (timeout > event->msSpinTime)
|
||||||
|
timeout -= event->msSpinTime;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spinTime -= timeout;
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t now = getMicrotime();
|
||||||
|
uint64_t end = now + spinTime * 1000;
|
||||||
|
while(!event->signaled)
|
||||||
|
{
|
||||||
|
now = getMicrotime();
|
||||||
|
if (now >= end)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->signaled)
|
||||||
|
{
|
||||||
|
if (event->reset)
|
||||||
|
event->signaled = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DWORD to = (timeout == TIMEOUT_INFINITE) ? INFINITE : (DWORD)timeout;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
switch(WaitForSingleObject(event->handle, to))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
if (!event->reset)
|
||||||
|
event->signaled = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
if (timeout == TIMEOUT_INFINITE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case WAIT_FAILED:
|
||||||
|
DEBUG_WINERROR("Wait for event failed", GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_ERROR("Unknown wait event return code");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lgWaitEvents(LGEvent * 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, handles, waitAll, to);
|
||||||
|
if (result >= WAIT_OBJECT_0 && result < count)
|
||||||
|
{
|
||||||
|
// null non signaled events from the handle list
|
||||||
|
for(int i = 0; i < count; ++i)
|
||||||
|
if (i != result && !lgWaitEvent(events[i], 0))
|
||||||
|
handles[i] = NULL;
|
||||||
|
free(handles);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result >= WAIT_ABANDONED_0 && result - WAIT_ABANDONED_0 < count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(result)
|
||||||
|
{
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
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 lgSignalEvent(LGEvent * event)
|
||||||
|
{
|
||||||
|
event->signaled = true;
|
||||||
|
return SetEvent(event->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lgResetEvent(LGEvent * event)
|
||||||
|
{
|
||||||
|
event->signaled = false;
|
||||||
|
return ResetEvent(event->handle);
|
||||||
|
}
|
93
common/src/platform/windows/thread.c
Normal file
93
common/src/platform/windows/thread.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/thread.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "common/windebug.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
struct LGThread
|
||||||
|
{
|
||||||
|
const char * name;
|
||||||
|
LGThreadFunction function;
|
||||||
|
void * opaque;
|
||||||
|
HANDLE handle;
|
||||||
|
DWORD threadID;
|
||||||
|
|
||||||
|
int resultCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
static DWORD WINAPI threadWrapper(LPVOID lpParameter)
|
||||||
|
{
|
||||||
|
LGThread * handle = (LGThread *)lpParameter;
|
||||||
|
handle->resultCode = handle->function(handle->opaque);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lgCreateThread(const char * name, LGThreadFunction function, void * opaque, LGThread ** handle)
|
||||||
|
{
|
||||||
|
*handle = (LGThread *)malloc(sizeof(LGThread));
|
||||||
|
(*handle)->name = name;
|
||||||
|
(*handle)->function = function;
|
||||||
|
(*handle)->opaque = opaque;
|
||||||
|
(*handle)->handle = CreateThread(NULL, 0, threadWrapper, *handle, 0, &(*handle)->threadID);
|
||||||
|
|
||||||
|
if (!(*handle)->handle)
|
||||||
|
{
|
||||||
|
free(*handle);
|
||||||
|
*handle = NULL;
|
||||||
|
DEBUG_WINERROR("CreateThread failed", GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lgJoinThread(LGThread * handle, int * resultCode)
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
switch(WaitForSingleObject(handle->handle, INFINITE))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
if (resultCode)
|
||||||
|
*resultCode = handle->resultCode;
|
||||||
|
CloseHandle(handle->handle);
|
||||||
|
free(handle);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case WAIT_FAILED:
|
||||||
|
DEBUG_WINERROR("Wait for thread failed", GetLastError());
|
||||||
|
CloseHandle(handle->handle);
|
||||||
|
free(handle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_WINERROR("Unknown failure waiting for thread", GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||||
https://looking-glass.hostfission.com
|
https://looking-glass.hostfission.com
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
@ -17,7 +17,7 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "windows/debug.h"
|
#include "common/windebug.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void DebugWinError(const char * file, const unsigned int line, const char * function, const char * desc, HRESULT status)
|
void DebugWinError(const char * file, const unsigned int line, const char * function, const char * desc, HRESULT status)
|
Loading…
Reference in New Issue
Block a user