LilyPad: Fixed a potential threading issue when read input in gs thread is disabled. Odds of the issue being a problem, while perhaps significantly greater than 1/<number of atoms in the universe>, weren't too high.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1025 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
mattmenke 2009-04-19 23:04:21 +00:00
parent 457b78e70e
commit 256d32037c
8 changed files with 83 additions and 47 deletions

View File

@ -840,9 +840,7 @@ int LoadSettings(int force, wchar_t *file) {
} }
if (config.debug) { if (config.debug) {
HANDLE hFile = CreateFileA("logs\\padLog.txt", GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); CreateDirectory(L"logs", 0);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
else CreateDirectory(L"logs", 0);
} }
@ -1472,7 +1470,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
if (GetBinding(port, slot, selIndex, dev, b, ffb)) { if (GetBinding(port, slot, selIndex, dev, b, ffb)) {
selected = 0xFF; selected = 0xFF;
InitInfo info = {0, hWndProp, hWnd, GetDlgItem(hWnd, cmd)}; InitInfo info = {0, hWndProp, hWnd, GetDlgItem(hWnd, cmd)};
EatWndProc(info.hWndButton, DoNothingWndProc); EatWndProc(info.hWndButton, DoNothingWndProc, 0);
for (int i=0; i<dm->numDevices; i++) { for (int i=0; i<dm->numDevices; i++) {
if (dm->devices[i] != dev) { if (dm->devices[i] != dev) {
dm->DisableDevice(i); dm->DisableDevice(i);
@ -1507,7 +1505,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
} }
InitInfo info = {selected==0x7F, hWndProp, hWnd, GetDlgItem(hWnd, cmd)}; InitInfo info = {selected==0x7F, hWndProp, hWnd, GetDlgItem(hWnd, cmd)};
EatWndProc(info.hWndButton, DoNothingWndProc); EatWndProc(info.hWndButton, DoNothingWndProc, 0);
int w = timeGetTime(); int w = timeGetTime();
dm->Update(&info); dm->Update(&info);
dm->PostRead(); dm->PostRead();

View File

@ -56,9 +56,7 @@ Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wc
void Device::FreeState() { void Device::FreeState() {
if (virtualControlState) free(virtualControlState); if (virtualControlState) free(virtualControlState);
virtualControlState = 0; virtualControlState = 0;
if (oldVirtualControlState) free(oldVirtualControlState);
oldVirtualControlState = 0; oldVirtualControlState = 0;
if (physicalControlState) free(physicalControlState);
physicalControlState = 0; physicalControlState = 0;
} }
@ -127,9 +125,9 @@ void Device::AddFFAxis(const wchar_t *displayName, int id) {
void Device::AllocState() { void Device::AllocState() {
FreeState(); FreeState();
virtualControlState = (int*) calloc(numVirtualControls, sizeof(int)); virtualControlState = (int*) calloc(numVirtualControls + numVirtualControls + numPhysicalControls, sizeof(int));
oldVirtualControlState = (int*) calloc(numVirtualControls, sizeof(int)); oldVirtualControlState = virtualControlState + numVirtualControls;
physicalControlState = (int*) calloc(numPhysicalControls, sizeof(int)); physicalControlState = oldVirtualControlState + numVirtualControls;
} }
void Device::FlipState() { void Device::FlipState() {
@ -213,6 +211,9 @@ VirtualControl *Device::GetVirtualControl(unsigned int uid) {
} }
VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlIndex) { VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlIndex) {
// Not really necessary, as always call AllocState when activated, but doesn't hurt.
FreeState();
if (numVirtualControls % 16 == 0) { if (numVirtualControls % 16 == 0) {
virtualControls = (VirtualControl*) realloc(virtualControls, sizeof(VirtualControl)*(numVirtualControls+16)); virtualControls = (VirtualControl*) realloc(virtualControls, sizeof(VirtualControl)*(numVirtualControls+16));
} }
@ -226,7 +227,9 @@ VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlI
} }
PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name) { PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name) {
// Not really necessary, as always call AllocState when activated, but doesn't hurt.
FreeState(); FreeState();
if (numPhysicalControls % 16 == 0) { if (numPhysicalControls % 16 == 0) {
physicalControls = (PhysicalControl*) realloc(physicalControls, sizeof(PhysicalControl)*(numPhysicalControls+16)); physicalControls = (PhysicalControl*) realloc(physicalControls, sizeof(PhysicalControl)*(numPhysicalControls+16));
} }

View File

@ -43,9 +43,9 @@ public:
InitInfo *info = (InitInfo*) d; InitInfo *info = (InitInfo*) d;
binding = info->bindingIgnore; binding = info->bindingIgnore;
if (info->hWndButton) if (info->hWndButton)
EatWndProc(info->hWndButton, StartHooksWndProc); EatWndProc(info->hWndButton, StartHooksWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
else else
EatWndProc(info->hWnd, StartHooksWndProc); EatWndProc(info->hWnd, StartHooksWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
InitState(); InitState();
ikhd = this; ikhd = this;
active = 1; active = 1;

View File

@ -63,6 +63,17 @@ int IsWindowMaximized (HWND hWnd) {
return 0; return 0;
} }
void DEBUG_TEXT_OUT(const char *text) {
if (config.debug) {
HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD junk;
WriteFile(hFile, text, strlen(text), &junk, 0);
CloseHandle(hFile);;
}
}
}
void DEBUG_NEW_SET() { void DEBUG_NEW_SET() {
if (config.debug && bufSize>1) { if (config.debug && bufSize>1) {
HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0); HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
@ -600,6 +611,7 @@ char* CALLBACK PS2EgetLibName(void) {
//} //}
void CALLBACK PADshutdown() { void CALLBACK PADshutdown() {
DEBUG_TEXT_OUT("LilyPad shutdown.\n\n");
for (int i=0; i<8; i++) for (int i=0; i<8; i++)
pads[i&1][i>>1].initialized = 0; pads[i&1][i>>1].initialized = 0;
portInitialized[0] = portInitialized[1] = 0; portInitialized[0] = portInitialized[1] = 0;
@ -664,9 +676,10 @@ s32 CALLBACK PADinit(u32 flags) {
} }
int port = (flags & 3); int port = (flags & 3);
if (port == 3) { if (port == 3) {
if (PADinit(1)) return -1; if (PADinit(1) == -1) return -1;
return PADinit(2); return PADinit(2);
} }
#ifdef _DEBUG #ifdef _DEBUG
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF; tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
@ -686,6 +699,8 @@ s32 CALLBACK PADinit(u32 flags) {
ClearKeyQueue(); ClearKeyQueue();
// Just in case, when resuming emulation. // Just in case, when resuming emulation.
ReleaseModifierKeys(); ReleaseModifierKeys();
DEBUG_TEXT_OUT("LilyPad initialized\n\n");
return 0; return 0;
} }
@ -806,6 +821,7 @@ DWORD WINAPI MaximizeWindowThreadProc(void *lpParameter) {
s32 CALLBACK PADopen(void *pDsp) { s32 CALLBACK PADopen(void *pDsp) {
if (openCount++) return 0; if (openCount++) return 0;
DEBUG_TEXT_OUT("LilyPad opened\n\n");
// Not really needed, shouldn't do anything. // Not really needed, shouldn't do anything.
if (LoadSettings()) return -1; if (LoadSettings()) return -1;
@ -825,12 +841,12 @@ s32 CALLBACK PADopen(void *pDsp) {
hWnd = GetParent (hWnd); hWnd = GetParent (hWnd);
// Implements most hacks, as well as enabling/disabling mouse // Implements most hacks, as well as enabling/disabling mouse
// capture when focus changes. // capture when focus changes.
if (!EatWndProc(hWnd, HackWndProc)) { if (!EatWndProc(hWnd, HackWndProc, 0)) {
openCount = 0; openCount = 0;
return -1; return -1;
} }
if (config.forceHide) { if (config.forceHide) {
EatWndProc(hWnd, HideCursorProc); EatWndProc(hWnd, HideCursorProc, 0);
} }
} }
@ -864,6 +880,8 @@ s32 CALLBACK PADopen(void *pDsp) {
void CALLBACK PADclose() { void CALLBACK PADclose() {
if (openCount && !--openCount) { if (openCount && !--openCount) {
DEBUG_TEXT_OUT("LilyPad closed\n\n");
deviceUpdateQueued = 0;
dm->ReleaseInput(); dm->ReleaseInput();
ReleaseEatenProc(); ReleaseEatenProc();
hWnd = 0; hWnd = 0;
@ -1011,6 +1029,7 @@ u8 CALLBACK PADpoll(u8 value) {
break; break;
// QUERY_DS2_ANALOG_MODE // QUERY_DS2_ANALOG_MODE
case 0x41: case 0x41:
// Right? Wrong? No clue.
if (pad->mode == MODE_DIGITAL) { if (pad->mode == MODE_DIGITAL) {
queryMaskMode[1] = queryMaskMode[2] = queryMaskMode[3] = 0; queryMaskMode[1] = queryMaskMode[2] = queryMaskMode[3] = 0;
queryMaskMode[6] = 0x00; queryMaskMode[6] = 0x00;

View File

@ -83,7 +83,7 @@ public:
} }
active = 1; active = 1;
if (!rawKeyboardActivatedCount++) { if (!rawKeyboardActivatedCount++) {
if (!rawMouseActivatedCount && !EatWndProc(hWnd, RawInputWndProc)) { if (!rawMouseActivatedCount && !EatWndProc(hWnd, RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate(); Deactivate();
return 0; return 0;
} }
@ -134,7 +134,7 @@ public:
// lines. // lines.
if (!rawMouseActivatedCount++) { if (!rawMouseActivatedCount++) {
GetMouseCapture(hWnd); GetMouseCapture(hWnd);
if (!rawKeyboardActivatedCount && !EatWndProc(hWnd, RawInputWndProc)) { if (!rawKeyboardActivatedCount && !EatWndProc(hWnd, RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate(); Deactivate();
return 0; return 0;
} }
@ -234,8 +234,8 @@ int InitializeRawInput() {
if (RawInputFailed) return 0; if (RawInputFailed) return 0;
if (!pGetRawInputDeviceList) { if (!pGetRawInputDeviceList) {
HMODULE user32 = LoadLibrary(L"user32.dll"); HMODULE user32 = LoadLibrary(L"user32.dll");
if (user32) { if (!user32 ||
if (!(pRegisterRawInputDevices = (_RegisterRawInputDevices) GetProcAddress(user32, "RegisterRawInputDevices")) || !(pRegisterRawInputDevices = (_RegisterRawInputDevices) GetProcAddress(user32, "RegisterRawInputDevices")) ||
!(pGetRawInputDeviceInfo = (_GetRawInputDeviceInfo) GetProcAddress(user32, "GetRawInputDeviceInfoW")) || !(pGetRawInputDeviceInfo = (_GetRawInputDeviceInfo) GetProcAddress(user32, "GetRawInputDeviceInfoW")) ||
!(pGetRawInputData = (_GetRawInputData) GetProcAddress(user32, "GetRawInputData")) || !(pGetRawInputData = (_GetRawInputData) GetProcAddress(user32, "GetRawInputData")) ||
!(pGetRawInputDeviceList = (_GetRawInputDeviceList) GetProcAddress(user32, "GetRawInputDeviceList"))) { !(pGetRawInputDeviceList = (_GetRawInputDeviceList) GetProcAddress(user32, "GetRawInputDeviceList"))) {
@ -244,7 +244,6 @@ int InitializeRawInput() {
return 0; return 0;
} }
} }
}
return 1; return 1;
} }
@ -288,7 +287,7 @@ void EnumRawInputDevices() {
wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID+3); wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID+3);
if (temp) *temp = 0; if (temp) *temp = 0;
displayName[0] = 0; int haveDescription = 0;
HKEY hKey; HKEY hKey;
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) { if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) {
DWORD type; DWORD type;
@ -300,16 +299,17 @@ void EnumRawInputDevices() {
else temp2++; else temp2++;
// Could do without this, but more effort than it's worth. // Could do without this, but more effort than it's worth.
wcscpy(keyName, temp2); wcscpy(keyName, temp2);
haveDescription = 1;
} }
RegCloseKey(hKey); RegCloseKey(hKey);
} }
if (list[i].dwType == RIM_TYPEKEYBOARD) { if (list[i].dwType == RIM_TYPEKEYBOARD) {
if (!displayName[0]) wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++); if (!haveDescription) wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++);
else wsprintfW(displayName, L"Raw KB: %s", keyName); else wsprintfW(displayName, L"Raw KB: %s", keyName);
dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID)); dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID));
} }
else if (list[i].dwType == RIM_TYPEMOUSE) { else if (list[i].dwType == RIM_TYPEMOUSE) {
if (!displayName[0]) wsprintfW(displayName, L"Raw Mouse %i", mouseCount++); if (!haveDescription) wsprintfW(displayName, L"Raw Mouse %i", mouseCount++);
else wsprintfW(displayName, L"Raw MS: %s", keyName); else wsprintfW(displayName, L"Raw MS: %s", keyName);
dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID)); dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID));
} }

View File

@ -28,9 +28,8 @@ public:
HWND hWnd = info->hWnd; HWND hWnd = info->hWnd;
if (info->hWndButton) { if (info->hWndButton) {
hWnd = info->hWndButton; hWnd = info->hWndButton;
// hWndDlg = info->hWnd;
} }
if (!wmm && !EatWndProc(hWnd, WindowsMessagingWndProc)) { if (!wmm && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate(); Deactivate();
return 0; return 0;
} }
@ -43,14 +42,13 @@ public:
} }
void Deactivate() { void Deactivate() {
FreeState();
if (active) { if (active) {
if (!wmm) if (!wmm)
ReleaseExtraProc(WindowsMessagingWndProc); ReleaseExtraProc(WindowsMessagingWndProc);
active = 0;
wmk = 0; wmk = 0;
active = 0;
FreeState();
} }
// hWndDlg = 0;
} }
@ -75,7 +73,7 @@ public:
hWnd = info->hWndButton; hWnd = info->hWndButton;
} }
if (!wmk && !EatWndProc(hWnd, WindowsMessagingWndProc)) { if (!wmk && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate(); Deactivate();
return 0; return 0;
} }
@ -90,13 +88,13 @@ public:
} }
void Deactivate() { void Deactivate() {
FreeState();
if (active) { if (active) {
ReleaseMouseCapture();
if (!wmk) if (!wmk)
ReleaseExtraProc(WindowsMessagingWndProc); ReleaseExtraProc(WindowsMessagingWndProc);
active = 0; ReleaseMouseCapture();
wmm = 0; wmm = 0;
active = 0;
FreeState();
} }
} }
}; };

View File

@ -2,7 +2,13 @@
static HWND hWndEaten = 0; static HWND hWndEaten = 0;
static WNDPROC eatenWndProc = 0; static WNDPROC eatenWndProc = 0;
static ExtraWndProc* extraProcs = 0;
struct ExtraWndProcInfo {
ExtraWndProc proc;
DWORD flags;
};
static ExtraWndProcInfo* extraProcs = 0;
static int numExtraProcs = 0; static int numExtraProcs = 0;
void ReleaseExtraProc(ExtraWndProc proc) { void ReleaseExtraProc(ExtraWndProc proc) {
@ -13,7 +19,7 @@ void ReleaseExtraProc(ExtraWndProc proc) {
if (hMutex) WaitForSingleObject(hMutex, 100); if (hMutex) WaitForSingleObject(hMutex, 100);
for (int i=0; i<numExtraProcs; i++) { for (int i=0; i<numExtraProcs; i++) {
if (extraProcs[i] == proc) { if (extraProcs[i].proc == proc) {
extraProcs[i] = extraProcs[--numExtraProcs]; extraProcs[i] = extraProcs[--numExtraProcs];
break; break;
} }
@ -35,9 +41,10 @@ void ReleaseExtraProc(ExtraWndProc proc) {
} }
void ReleaseEatenProc() { void ReleaseEatenProc() {
while (numExtraProcs) ReleaseExtraProc(extraProcs[0]); while (numExtraProcs) ReleaseExtraProc(extraProcs[0].proc);
} }
extern int deviceUpdateQueued;
LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
ExtraWndProcResult res = CONTINUE_BLISSFULLY; ExtraWndProcResult res = CONTINUE_BLISSFULLY;
LRESULT out = 0; LRESULT out = 0;
@ -45,16 +52,23 @@ LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
if (uMsg == WM_GETDLGCODE) { if (uMsg == WM_GETDLGCODE) {
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam); return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
} }
for (int i=0; i<numExtraProcs; i++) { for (int i=0; i<numExtraProcs; i++) {
ExtraWndProcResult res2 = extraProcs[i](hWnd, uMsg, wParam, lParam, &out); // Note: Second bit of deviceUpdateQueued is only set when I receive a device change
// notification, which is handled in the GS thread in one of the extraProcs, so this
// is all I need to prevent bad things from happening while updating devices. No mutex needed.
if ((deviceUpdateQueued&2) && (extraProcs[i].flags & EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) continue;
ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out);
if (res2 != res) { if (res2 != res) {
if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) { if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) {
ReleaseExtraProc(extraProcs[i]); ReleaseExtraProc(extraProcs[i].proc);
i--; i--;
} }
else if (res2 > res) res = res2; else if (res2 > res) res = res2;
} }
} }
if (res != NO_WND_PROC) { if (res != NO_WND_PROC) {
if (out == WM_DESTROY) { if (out == WM_DESTROY) {
ReleaseEatenProc(); ReleaseEatenProc();
@ -68,7 +82,7 @@ LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
} }
int EatWndProc(HWND hWnd, ExtraWndProc proc) { int EatWndProc(HWND hWnd, ExtraWndProc proc, DWORD flags) {
// Probably isn't needed, but just in case... // Probably isn't needed, but just in case...
// Creating and destroying the mutex adds some inefficiency, // Creating and destroying the mutex adds some inefficiency,
// but this function is only called on emulation start and on focus/unfocus. // but this function is only called on emulation start and on focus/unfocus.
@ -83,8 +97,10 @@ int EatWndProc(HWND hWnd, ExtraWndProc proc) {
hWndEaten = hWnd; hWndEaten = hWnd;
} }
if (hWndEaten == hWnd) { if (hWndEaten == hWnd) {
extraProcs = (ExtraWndProc*) realloc(extraProcs, sizeof(ExtraWndProc)*(numExtraProcs+1)); extraProcs = (ExtraWndProcInfo*) realloc(extraProcs, sizeof(ExtraWndProcInfo)*(numExtraProcs+1));
extraProcs[numExtraProcs++] = proc; extraProcs[numExtraProcs].proc = proc;
extraProcs[numExtraProcs].flags = flags;
numExtraProcs++;
} }
if (hMutex) { if (hMutex) {

View File

@ -1,5 +1,7 @@
#include "Global.h" #include "Global.h"
#define EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES 1
/* Need this to let window be subclassed multiple times but still clean up nicely. /* Need this to let window be subclassed multiple times but still clean up nicely.
*/ */
enum ExtraWndProcResult { enum ExtraWndProcResult {
@ -11,7 +13,7 @@ enum ExtraWndProcResult {
}; };
typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out); typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out);
int EatWndProc(HWND hWnd, ExtraWndProc proc); int EatWndProc(HWND hWnd, ExtraWndProc proc, DWORD flags);
void ReleaseExtraProc(ExtraWndProc proc); void ReleaseExtraProc(ExtraWndProc proc);
void ReleaseEatenProc(); void ReleaseEatenProc();