From fc0ab2b20d0105278cda5255d0e7b2eda3980706 Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida Date: Tue, 22 Sep 2020 11:14:05 -0300 Subject: [PATCH] win32: Fix wait win32 objects with 64 or more objects Code was using MsgWaitForMultipleObjects in threads where there were no Windows, and the main thread used WaitForMultipleObjects, which caused timeout even if input messages had to be handled. Also, the quit thread also waited for all threads, which meant waiting for timeout. The fix consisted in using MsgWaitForMultipleObjects in the main thread instead and creating a quit event that made WaitForMultipleObjects return when a signalled event or message was found. --- src/lib/ecore/ecore_main.c | 52 +++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index 4bca7759f1..00605e27f8 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -2547,6 +2547,7 @@ typedef struct { DWORD objects_nbr; HANDLE *objects; + HANDLE *event; DWORD timeout; } Ecore_Main_Win32_Thread_Data; @@ -2554,11 +2555,10 @@ static unsigned int __stdcall _ecore_main_win32_objects_wait_thread(void *data) { Ecore_Main_Win32_Thread_Data *td = (Ecore_Main_Win32_Thread_Data *)data; - return MsgWaitForMultipleObjects(td->objects_nbr, - (const HANDLE *)td->objects, - FALSE, - td->timeout, - QS_ALLINPUT); + return WaitForMultipleObjects(td->objects_nbr + 1, // plus event to quit + (const HANDLE *)td->objects, + FALSE, + td->timeout); } static DWORD @@ -2578,8 +2578,8 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, // too much objects, so we launch a bunch of threads to // wait for, each one calls MsgWaitForMultipleObjects - threads_nbr = objects_nbr / (MAXIMUM_WAIT_OBJECTS - 1); - threads_remain = objects_nbr % (MAXIMUM_WAIT_OBJECTS - 1); + threads_nbr = objects_nbr / (MAXIMUM_WAIT_OBJECTS - 2); // minus quit event + threads_remain = objects_nbr % (MAXIMUM_WAIT_OBJECTS - 2); if (threads_remain > 0) threads_nbr++; if (threads_nbr > MAXIMUM_WAIT_OBJECTS) @@ -2606,8 +2606,9 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, objects_idx = 0; for (i = 0; i < threads_nbr; i++) { + DWORD cur_objects_idx = objects_idx; threads_data[i].timeout = timeout; - threads_data[i].objects = (HANDLE *)objects + objects_idx; + threads_data[i].event = CreateEvent(NULL, TRUE, FALSE, NULL); if ((i == (threads_nbr - 1)) && (threads_remain != 0)) { @@ -2616,10 +2617,15 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, } else { - threads_data[i].objects_nbr = (MAXIMUM_WAIT_OBJECTS - 1); - objects_idx += (MAXIMUM_WAIT_OBJECTS - 1); + threads_data[i].objects_nbr = (MAXIMUM_WAIT_OBJECTS - 2); // minus quit event + objects_idx += (MAXIMUM_WAIT_OBJECTS - 2); } + // copy objects and add quit event + threads_data[i].objects = (HANDLE*)malloc(sizeof(HANDLE*) * (threads_data[i].objects_nbr+1)); + memcpy(threads_data[i].objects, objects + cur_objects_idx, threads_data[i].objects_nbr*sizeof(HANDLE*)); + threads_data[i].objects[threads_data[i].objects_nbr] = threads_data[i].event; + threads_handles[i] = (HANDLE)_beginthreadex (NULL, 0, _ecore_main_win32_objects_wait_thread, &threads_data[i], 0, NULL); @@ -2628,18 +2634,24 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, DWORD j; ERR("Can not create the waiting threads."); + for (j = 0; j != i; j++) + SetEvent(threads_data[j].event); WaitForMultipleObjects(i, threads_handles, TRUE, INFINITE); for (j = 0; j < i; j++) - CloseHandle(threads_handles[i]); + CloseHandle(threads_handles[j]); + for (j = 0; j != i; j++) + CloseHandle(threads_data[j].event); + for (j = 0; j != i; j++) + free(threads_data[j].objects); goto free_threads_data; } } - result = WaitForMultipleObjects(threads_nbr, - threads_handles, - FALSE, // we wait until one thread signaled - INFINITE); + result = MsgWaitForMultipleObjects(threads_nbr, + threads_handles, + FALSE, // we wait until one thread signaled + INFINITE, QS_ALLINPUT); if (result < (WAIT_OBJECT_0 + threads_nbr)) { @@ -2651,15 +2663,25 @@ _ecore_main_win32_objects_wait(DWORD objects_nbr, if (GetExitCodeThread(threads_handles[result - WAIT_OBJECT_0], &wait_res)) { + for (i = 0; i < threads_nbr; i++) + SetEvent(threads_data[i].event); WaitForMultipleObjects(threads_nbr, threads_handles, TRUE, INFINITE); for (i = 0; i < threads_nbr; i++) CloseHandle(threads_handles[i]); + for (i = 0; i < threads_nbr; i++) + CloseHandle(threads_data[i].event); + for (i = 0; i < threads_nbr; i++) + free(threads_data[i].objects); free(threads_data); free(threads_handles); return wait_res; } } + else if (result == (WAIT_OBJECT_0 + threads_nbr)) + return WAIT_OBJECT_0 + objects_nbr; + else if (result == WAIT_TIMEOUT) + return WAIT_OBJECT_0 + objects_nbr; else { ERR("Error when waiting threads.");