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) {
HANDLE hFile = CreateFileA("logs\\padLog.txt", GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
else CreateDirectory(L"logs", 0);
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)) {
selected = 0xFF;
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++) {
if (dm->devices[i] != dev) {
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)};
EatWndProc(info.hWndButton, DoNothingWndProc);
EatWndProc(info.hWndButton, DoNothingWndProc, 0);
int w = timeGetTime();
dm->Update(&info);
dm->PostRead();

View File

@ -56,9 +56,7 @@ Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wc
void Device::FreeState() {
if (virtualControlState) free(virtualControlState);
virtualControlState = 0;
if (oldVirtualControlState) free(oldVirtualControlState);
oldVirtualControlState = 0;
if (physicalControlState) free(physicalControlState);
physicalControlState = 0;
}
@ -127,9 +125,9 @@ void Device::AddFFAxis(const wchar_t *displayName, int id) {
void Device::AllocState() {
FreeState();
virtualControlState = (int*) calloc(numVirtualControls, sizeof(int));
oldVirtualControlState = (int*) calloc(numVirtualControls, sizeof(int));
physicalControlState = (int*) calloc(numPhysicalControls, sizeof(int));
virtualControlState = (int*) calloc(numVirtualControls + numVirtualControls + numPhysicalControls, sizeof(int));
oldVirtualControlState = virtualControlState + numVirtualControls;
physicalControlState = oldVirtualControlState + numVirtualControls;
}
void Device::FlipState() {
@ -213,6 +211,9 @@ VirtualControl *Device::GetVirtualControl(unsigned int uid) {
}
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) {
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) {
// Not really necessary, as always call AllocState when activated, but doesn't hurt.
FreeState();
if (numPhysicalControls % 16 == 0) {
physicalControls = (PhysicalControl*) realloc(physicalControls, sizeof(PhysicalControl)*(numPhysicalControls+16));
}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,13 @@
static HWND hWndEaten = 0;
static WNDPROC eatenWndProc = 0;
static ExtraWndProc* extraProcs = 0;
struct ExtraWndProcInfo {
ExtraWndProc proc;
DWORD flags;
};
static ExtraWndProcInfo* extraProcs = 0;
static int numExtraProcs = 0;
void ReleaseExtraProc(ExtraWndProc proc) {
@ -13,7 +19,7 @@ void ReleaseExtraProc(ExtraWndProc proc) {
if (hMutex) WaitForSingleObject(hMutex, 100);
for (int i=0; i<numExtraProcs; i++) {
if (extraProcs[i] == proc) {
if (extraProcs[i].proc == proc) {
extraProcs[i] = extraProcs[--numExtraProcs];
break;
}
@ -35,9 +41,10 @@ void ReleaseExtraProc(ExtraWndProc proc) {
}
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) {
ExtraWndProcResult res = CONTINUE_BLISSFULLY;
LRESULT out = 0;
@ -45,16 +52,23 @@ LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
if (uMsg == WM_GETDLGCODE) {
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
}
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 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) {
ReleaseExtraProc(extraProcs[i]);
ReleaseExtraProc(extraProcs[i].proc);
i--;
}
else if (res2 > res) res = res2;
}
}
if (res != NO_WND_PROC) {
if (out == WM_DESTROY) {
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...
// Creating and destroying the mutex adds some inefficiency,
// 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;
}
if (hWndEaten == hWnd) {
extraProcs = (ExtraWndProc*) realloc(extraProcs, sizeof(ExtraWndProc)*(numExtraProcs+1));
extraProcs[numExtraProcs++] = proc;
extraProcs = (ExtraWndProcInfo*) realloc(extraProcs, sizeof(ExtraWndProcInfo)*(numExtraProcs+1));
extraProcs[numExtraProcs].proc = proc;
extraProcs[numExtraProcs].flags = flags;
numExtraProcs++;
}
if (hMutex) {

View File

@ -1,5 +1,7 @@
#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.
*/
enum ExtraWndProcResult {
@ -11,7 +13,7 @@ enum ExtraWndProcResult {
};
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 ReleaseEatenProc();