2014-01-25 03:08:06 +04:00
|
|
|
|
|
|
|
#include <winpr/crt.h>
|
|
|
|
#include <winpr/synch.h>
|
2014-01-25 07:44:23 +04:00
|
|
|
#include <winpr/sysinfo.h>
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
static int g_Count = 0;
|
|
|
|
static HANDLE g_Event = NULL;
|
|
|
|
|
|
|
|
struct apc_data
|
|
|
|
{
|
|
|
|
UINT32 StartTime;
|
|
|
|
};
|
|
|
|
typedef struct apc_data APC_DATA;
|
2014-01-25 03:08:06 +04:00
|
|
|
|
|
|
|
VOID CALLBACK TimerAPCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
|
|
|
|
{
|
2014-01-25 07:44:23 +04:00
|
|
|
APC_DATA* apcData;
|
|
|
|
UINT32 CurrentTime = GetTickCount();
|
2014-01-25 03:08:06 +04:00
|
|
|
|
|
|
|
if (!lpArg)
|
|
|
|
return;
|
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
apcData = (APC_DATA*) lpArg;
|
|
|
|
|
|
|
|
printf("TimerAPCProc: time: %d\n", CurrentTime - apcData->StartTime);
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
g_Count++;
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
if (g_Count >= 5)
|
|
|
|
{
|
|
|
|
SetEvent(g_Event);
|
|
|
|
}
|
2014-01-25 03:08:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int TestSynchWaitableTimerAPC(int argc, char* argv[])
|
|
|
|
{
|
2014-11-17 01:10:33 +03:00
|
|
|
int status = -1;
|
|
|
|
HANDLE hTimer = NULL;
|
2014-01-25 03:08:06 +04:00
|
|
|
BOOL bSuccess;
|
2014-01-25 07:44:23 +04:00
|
|
|
LARGE_INTEGER due;
|
2014-11-17 01:10:33 +03:00
|
|
|
APC_DATA* apcData = NULL;
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
apcData = (APC_DATA*) malloc(sizeof(APC_DATA));
|
2015-04-03 17:21:01 +03:00
|
|
|
if (!apcData)
|
|
|
|
{
|
|
|
|
printf("Memory allocation failed\n");
|
2015-04-28 18:00:41 +03:00
|
|
|
goto cleanup;
|
2015-04-03 17:21:01 +03:00
|
|
|
}
|
2015-04-28 18:00:41 +03:00
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
g_Event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
2015-04-28 18:00:41 +03:00
|
|
|
if (!g_Event)
|
|
|
|
{
|
|
|
|
printf("Failed to create event\n");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-01-25 03:08:06 +04:00
|
|
|
hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
|
|
|
|
|
|
|
|
if (!hTimer)
|
2014-11-17 01:10:33 +03:00
|
|
|
goto cleanup;
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
due.QuadPart = -15000000LL; /* 1.5 seconds */
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2014-01-25 07:44:23 +04:00
|
|
|
apcData->StartTime = GetTickCount();
|
|
|
|
bSuccess = SetWaitableTimer(hTimer, &due, 2000, TimerAPCProc, apcData, FALSE);
|
2014-01-25 03:08:06 +04:00
|
|
|
|
|
|
|
if (!bSuccess)
|
2014-11-17 01:10:33 +03:00
|
|
|
goto cleanup;
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2016-05-24 23:33:27 +03:00
|
|
|
/**
|
|
|
|
* See Remarks at https://msdn.microsoft.com/en-us/library/windows/desktop/ms686786(v=vs.85).aspx
|
|
|
|
* The SetWaitableTimer completion routine is executed by the thread that activates the timer
|
|
|
|
* using SetWaitableTimer. However, the thread must be in an ALERTABLE state.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Note: On WIN32 we need to use WaitForSingleObjectEx with parameter bAlertable = TRUE
|
|
|
|
* However, WinPR currently (May 2016) does not have a working WaitForSingleObjectEx implementation
|
|
|
|
* but its non-WIN32 WaitForSingleObject implementations seem to be alertable by WinPR's
|
|
|
|
* timer implementations.
|
|
|
|
**/
|
|
|
|
|
|
|
|
for(;;)
|
2014-01-25 03:08:06 +04:00
|
|
|
{
|
2016-05-24 23:33:27 +03:00
|
|
|
DWORD rc;
|
|
|
|
#ifdef _WIN32
|
|
|
|
rc = WaitForSingleObjectEx(g_Event, INFINITE, TRUE);
|
|
|
|
#else
|
|
|
|
rc = WaitForSingleObject(g_Event, INFINITE);
|
|
|
|
#endif
|
|
|
|
if (rc == WAIT_OBJECT_0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (rc == 0x000000C0L) /* WAIT_IO_COMPLETION */
|
|
|
|
continue;
|
|
|
|
|
|
|
|
printf("Failed to wait for completion event (%u)\n", GetLastError());
|
2014-11-17 01:10:33 +03:00
|
|
|
goto cleanup;
|
2014-01-25 03:08:06 +04:00
|
|
|
}
|
|
|
|
|
2014-11-17 01:10:33 +03:00
|
|
|
status = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2014-11-17 01:52:22 +03:00
|
|
|
if (hTimer)
|
2014-11-17 01:10:33 +03:00
|
|
|
CloseHandle(hTimer);
|
|
|
|
if (g_Event)
|
|
|
|
CloseHandle(g_Event);
|
2015-05-11 10:07:39 +03:00
|
|
|
free(apcData);
|
2014-01-25 03:08:06 +04:00
|
|
|
|
2016-06-07 18:20:56 +03:00
|
|
|
#ifdef __APPLE__
|
|
|
|
if (status == 0)
|
|
|
|
{
|
|
|
|
printf("%s: Error, this test is currently expected not to succeed on this platform.\n",
|
|
|
|
__FUNCTION__);
|
|
|
|
status = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("%s: This test is currently expected to fail on this platform.\n",
|
|
|
|
__FUNCTION__);
|
|
|
|
status = 0;
|
|
|
|
}
|
|
|
|
#endif
|
2014-11-17 01:10:33 +03:00
|
|
|
return status;
|
2014-01-25 03:08:06 +04:00
|
|
|
}
|
|
|
|
|