Added WaitableTimer implementation for mac OS.

This commit is contained in:
Armin Novak 2018-03-08 13:46:46 +01:00
parent 14997f96e3
commit 9bd13c25c9
10 changed files with 234 additions and 94 deletions

View File

@ -135,7 +135,7 @@ static DWORD mac_client_update_thread(void* param)
return 0; return 0;
} }
static DWORD mac_client_input_thread(void* param) static DWORD WINAPI mac_client_input_thread(LPVOID param)
{ {
int status; int status;
wMessage message; wMessage message;
@ -194,8 +194,7 @@ DWORD mac_client_thread(void* param)
if (settings->AsyncInput) if (settings->AsyncInput)
{ {
if (!(inputThread = CreateThread(NULL, 0, if (!(inputThread = CreateThread(NULL, 0, mac_client_input_thread, context, 0, NULL)))
(LPTHREAD_START_ROUTINE) mac_client_input_thread, context, 0, NULL)))
{ {
WLog_ERR(TAG, "failed to create async input thread"); WLog_ERR(TAG, "failed to create async input thread");
goto disconnect; goto disconnect;
@ -738,7 +737,7 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
- (void) onPasteboardTimerFired :(NSTimer*) timer - (void) onPasteboardTimerFired :(NSTimer*) timer
{ {
BYTE* data; const BYTE* data;
UINT32 size; UINT32 size;
UINT32 formatId; UINT32 formatId;
BOOL formatMatch; BOOL formatMatch;

View File

@ -1521,7 +1521,7 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
} }
settings = context->settings; settings = context->settings;
timer = CreateWaitableTimerA(NULL, FALSE, NULL); timer = CreateWaitableTimerA(NULL, FALSE, "mainloop-periodic-timer");
if (!timer) if (!timer)
{ {
@ -1581,7 +1581,7 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
nCount += tmp; nCount += tmp;
} }
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 100); waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (waitStatus == WAIT_FAILED) if (waitStatus == WAIT_FAILED)
break; break;
@ -1609,7 +1609,7 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
} }
} }
if (status != WAIT_TIMEOUT && WaitForSingleObject(timer, 0)) if ((status != WAIT_TIMEOUT) && (waitStatus == WAIT_OBJECT_0))
{ {
timerEvent.now = GetTickCount64(); timerEvent.now = GetTickCount64();
PubSub_OnTimer(context->pubSub, context, &timerEvent); PubSub_OnTimer(context->pubSub, context, &timerEvent);

View File

@ -817,7 +817,7 @@ static int freerdp_client_command_line_post_filter(void* context,
return status ? 1 : -1; return status ? 1 : -1;
} }
BOOL freerdp_parse_username(char* username, char** user, char** domain) BOOL freerdp_parse_username(const char* username, char** user, char** domain)
{ {
char* p; char* p;
int length = 0; int length = 0;
@ -871,7 +871,7 @@ BOOL freerdp_parse_username(char* username, char** user, char** domain)
return TRUE; return TRUE;
} }
BOOL freerdp_parse_hostname(char* hostname, char** host, int* port) BOOL freerdp_parse_hostname(const char* hostname, char** host, int* port)
{ {
char* p; char* p;
p = strrchr(hostname, ':'); p = strrchr(hostname, ':');

View File

@ -44,8 +44,8 @@ FREERDP_API BOOL freerdp_client_print_command_line_help(int argc, char** argv);
FREERDP_API BOOL freerdp_client_print_command_line_help_ex( FREERDP_API BOOL freerdp_client_print_command_line_help_ex(
int argc, char** argv, COMMAND_LINE_ARGUMENT_A* custom); int argc, char** argv, COMMAND_LINE_ARGUMENT_A* custom);
FREERDP_API BOOL freerdp_parse_username(char* username, char** user, char** domain); FREERDP_API BOOL freerdp_parse_username(const char* username, char** user, char** domain);
FREERDP_API BOOL freerdp_parse_hostname(char* hostname, char** host, int* port); FREERDP_API BOOL freerdp_parse_hostname(const char* hostname, char** host, int* port);
FREERDP_API BOOL freerdp_set_connection_type(rdpSettings* settings, int type); FREERDP_API BOOL freerdp_set_connection_type(rdpSettings* settings, int type);
FREERDP_API BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params); FREERDP_API BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params);

View File

@ -14,14 +14,17 @@ VERSION=$(echo $STR_VERSION | cut -d ' ' -f4)
MAJOR_VERSION=$(echo $VERSION | cut -d'.' -f1) MAJOR_VERSION=$(echo $VERSION | cut -d'.' -f1)
MINOR_VERSION=$(echo $VERSION | cut -d'.' -f2) MINOR_VERSION=$(echo $VERSION | cut -d'.' -f2)
if [ "$MAJOR_VERSION" -lt "2" ]; then if [ "$MAJOR_VERSION" -lt "2" ];
echo "Your version of astyle($VERSION) is too old, need at least 2.03" then
exit 1
fi
if [ "$MINOR_VERSION" -lt "3" ]; then
echo "Your version of astyle($VERSION) is too old, need at least 2.03" echo "Your version of astyle($VERSION) is too old, need at least 2.03"
exit 1 exit 1
elif [ "$MAJOR_VERSION" -eq "2" ];
then
if [ "$MINOR_VERSION" -lt "3" ];
then
echo "Your version of astyle($VERSION) is too old, need at least 2.03"
exit 1
fi
fi fi
if [ $# -le 0 ]; then if [ $# -le 0 ]; then
@ -31,9 +34,9 @@ if [ $# -le 0 ]; then
fi fi
$ASTYLE --lineend=linux --mode=c --indent=tab=4 --pad-header --pad-oper --style=allman --min-conditional-indent=0 \ $ASTYLE --lineend=linux --mode=c --indent=tab=4 --pad-header --pad-oper --style=allman --min-conditional-indent=0 \
--indent-switches --indent-cases --indent-preprocessor -k1 --max-code-length=100 \ --indent-switches --indent-cases --indent-preprocessor -k1 --max-code-length=100 \
--indent-col1-comments --delete-empty-lines --break-closing-brackets \ --indent-col1-comments --delete-empty-lines --break-closing-brackets \
--align-pointer=type --indent-labels -xe --break-after-logical \ --align-pointer=type --indent-labels -xe --break-after-logical \
--unpad-paren --break-blocks $@ --unpad-paren --break-blocks $@
exit $? exit $?

View File

@ -34,6 +34,12 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#if defined(__APPLE__)
#include <mach/task.h>
#include <mach/mach.h>
#include <mach/semaphore.h>
#endif
#ifndef _WIN32 #ifndef _WIN32
#include "../log.h" #include "../log.h"
@ -44,7 +50,8 @@ VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
InitializeCriticalSectionEx(lpCriticalSection, 0, 0); InitializeCriticalSectionEx(lpCriticalSection, 0, 0);
} }
BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags) BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount,
DWORD Flags)
{ {
/** /**
* See http://msdn.microsoft.com/en-us/library/ff541979(v=vs.85).aspx * See http://msdn.microsoft.com/en-us/library/ff541979(v=vs.85).aspx
@ -67,18 +74,24 @@ BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwS
lpCriticalSection->RecursionCount = 0; lpCriticalSection->RecursionCount = 0;
lpCriticalSection->OwningThread = NULL; lpCriticalSection->OwningThread = NULL;
lpCriticalSection->LockSemaphore = (winpr_sem_t*) malloc(sizeof(winpr_sem_t)); lpCriticalSection->LockSemaphore = (winpr_sem_t*) malloc(sizeof(winpr_sem_t));
if (!lpCriticalSection->LockSemaphore) if (!lpCriticalSection->LockSemaphore)
return FALSE; return FALSE;
#if defined(__APPLE__) #if defined(__APPLE__)
if (semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO, 0) != KERN_SUCCESS)
if (semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO,
0) != KERN_SUCCESS)
goto out_fail; goto out_fail;
#else #else
if(sem_init(lpCriticalSection->LockSemaphore, 0, 0) != 0)
if (sem_init(lpCriticalSection->LockSemaphore, 0, 0) != 0)
goto out_fail; goto out_fail;
#endif #endif
SetCriticalSectionSpinCount(lpCriticalSection, dwSpinCount); SetCriticalSectionSpinCount(lpCriticalSection, dwSpinCount);
return TRUE; return TRUE;
out_fail: out_fail:
free(lpCriticalSection->LockSemaphore); free(lpCriticalSection->LockSemaphore);
return FALSE; return FALSE;
@ -150,7 +163,7 @@ VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
} }
/* Failed to get the lock. Let the scheduler know that we're spinning. */ /* Failed to get the lock. Let the scheduler know that we're spinning. */
if (sched_yield()!=0) if (sched_yield() != 0)
{ {
/** /**
* On some operating systems sched_yield is a stub. * On some operating systems sched_yield is a stub.

View File

@ -86,6 +86,10 @@ typedef struct winpr_event WINPR_EVENT;
#include <sys/timerfd.h> #include <sys/timerfd.h>
#endif #endif
#if defined(__APPLE__)
#include <dispatch/dispatch.h>
#endif
struct winpr_timer struct winpr_timer
{ {
WINPR_HANDLE_DEF(); WINPR_HANDLE_DEF();
@ -96,11 +100,17 @@ struct winpr_timer
BOOL bManualReset; BOOL bManualReset;
PTIMERAPCROUTINE pfnCompletionRoutine; PTIMERAPCROUTINE pfnCompletionRoutine;
LPVOID lpArgToCompletionRoutine; LPVOID lpArgToCompletionRoutine;
#ifdef WITH_POSIX_TIMER #ifdef WITH_POSIX_TIMER
timer_t tid; timer_t tid;
struct itimerspec timeout; struct itimerspec timeout;
#endif #endif
#if defined(__APPLE__)
dispatch_queue_t queue;
dispatch_source_t source;
int pipe[2];
BOOL running;
#endif
}; };
typedef struct winpr_timer WINPR_TIMER; typedef struct winpr_timer WINPR_TIMER;
@ -109,7 +119,7 @@ typedef struct winpr_timer_queue_timer WINPR_TIMER_QUEUE_TIMER;
struct winpr_timer_queue struct winpr_timer_queue
{ {
WINPR_HANDLE_DEF(); WINPR_HANDLE_DEF();
pthread_t thread; pthread_t thread;
pthread_attr_t attr; pthread_attr_t attr;
pthread_mutex_t mutex; pthread_mutex_t mutex;
@ -132,7 +142,7 @@ struct winpr_timer_queue_timer
DWORD Period; DWORD Period;
PVOID Parameter; PVOID Parameter;
WAITORTIMERCALLBACK Callback; WAITORTIMERCALLBACK Callback;
int FireCount; int FireCount;
struct timespec StartTime; struct timespec StartTime;

View File

@ -9,7 +9,6 @@ int TestSynchWaitableTimer(int argc, char* argv[])
LONG period; LONG period;
LARGE_INTEGER due; LARGE_INTEGER due;
int result = -1; int result = -1;
timer = CreateWaitableTimer(NULL, FALSE, NULL); timer = CreateWaitableTimer(NULL, FALSE, NULL);
if (!timer) if (!timer)
@ -35,17 +34,16 @@ int TestSynchWaitableTimer(int argc, char* argv[])
} }
printf("Timer Signaled\n"); printf("Timer Signaled\n");
status = WaitForSingleObject(timer, 2000); status = WaitForSingleObject(timer, 2000);
if (status != WAIT_TIMEOUT) if (status != WAIT_TIMEOUT)
{ {
printf("WaitForSingleObject(timer, 2000) failure: Actual: 0x%08"PRIX32", Expected: 0x%08X\n", status, WAIT_TIMEOUT); printf("WaitForSingleObject(timer, 2000) failure: Actual: 0x%08"PRIX32", Expected: 0x%08X\n",
status, WAIT_TIMEOUT);
goto out; goto out;
} }
due.QuadPart = 0; due.QuadPart = 0;
period = 1200; /* 1.2 seconds */ period = 1200; /* 1.2 seconds */
if (!SetWaitableTimer(timer, &due, period, NULL, NULL, 0)) if (!SetWaitableTimer(timer, &due, period, NULL, NULL, 0))
@ -62,6 +60,12 @@ int TestSynchWaitableTimer(int argc, char* argv[])
printf("Timer Signaled\n"); printf("Timer Signaled\n");
if (!SetWaitableTimer(timer, &due, period, NULL, NULL, 0))
{
printf("SetWaitableTimer failure\n");
goto out;
}
if (WaitForMultipleObjects(1, &timer, FALSE, INFINITE) != WAIT_OBJECT_0) if (WaitForMultipleObjects(1, &timer, FALSE, INFINITE) != WAIT_OBJECT_0)
{ {
printf("WaitForMultipleObjects(timer, INFINITE) failure\n"); printf("WaitForMultipleObjects(timer, INFINITE) failure\n");
@ -69,28 +73,9 @@ int TestSynchWaitableTimer(int argc, char* argv[])
} }
printf("Timer Signaled\n"); printf("Timer Signaled\n");
result = 0; result = 0;
out: out:
CloseHandle(timer); CloseHandle(timer);
#ifdef __APPLE__
if (result == 0)
{
printf("%s: Error, this test is currently expected not to succeed on this platform.\n",
__FUNCTION__);
result = -1;
}
else
{
printf("%s: This test is currently expected to fail on this platform.\n",
__FUNCTION__);
result = 0;
}
#endif
return result; return result;
} }

View File

@ -12,7 +12,7 @@ struct apc_data
}; };
typedef struct apc_data APC_DATA; typedef struct apc_data APC_DATA;
VOID CALLBACK TimerAPCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue) static VOID CALLBACK TimerAPCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
{ {
APC_DATA* apcData; APC_DATA* apcData;
UINT32 CurrentTime = GetTickCount(); UINT32 CurrentTime = GetTickCount();
@ -108,20 +108,6 @@ cleanup:
CloseHandle(g_Event); CloseHandle(g_Event);
free(apcData); free(apcData);
#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
return status; return status;
} }

View File

@ -77,14 +77,24 @@ static DWORD TimerCleanupHandle(HANDLE handle)
if (!TimerIsHandled(handle)) if (!TimerIsHandled(handle))
return WAIT_FAILED; return WAIT_FAILED;
if (timer->bManualReset)
return WAIT_OBJECT_0;
length = read(timer->fd, (void*) &expirations, sizeof(UINT64)); length = read(timer->fd, (void*) &expirations, sizeof(UINT64));
if (length != 8) if (length != 8)
{ {
if (length == -1) if (length == -1)
{ {
if (errno == ETIMEDOUT) switch (errno)
return WAIT_TIMEOUT; {
case ETIMEDOUT:
case EAGAIN:
return WAIT_TIMEOUT;
default:
break;
}
WLog_ERR(TAG, "timer read() failure [%d] %s", errno, strerror(errno)); WLog_ERR(TAG, "timer read() failure [%d] %s", errno, strerror(errno));
} }
@ -123,6 +133,17 @@ BOOL TimerCloseHandle(HANDLE handle)
#endif #endif
} }
#if defined(__APPLE__)
dispatch_release(timer->queue);
dispatch_release(timer->source);
if (timer->pipe[0] != -1)
close(timer->pipe[0]);
if (timer->pipe[1] != -1)
close(timer->pipe[1]);
#endif
free(timer); free(timer);
return TRUE; return TRUE;
} }
@ -131,11 +152,11 @@ BOOL TimerCloseHandle(HANDLE handle)
static BOOL g_WaitableTimerSignalHandlerInstalled = FALSE; static BOOL g_WaitableTimerSignalHandlerInstalled = FALSE;
static void WaitableTimerSignalHandler(int signum, siginfo_t* siginfo, void* arg) static void WaitableTimerHandler(void* arg)
{ {
WINPR_TIMER* timer = siginfo->si_value.sival_ptr; WINPR_TIMER* timer = (WINPR_TIMER*)arg;
if (!timer || (signum != SIGALRM)) if (!timer)
return; return;
if (timer->pfnCompletionRoutine) if (timer->pfnCompletionRoutine)
@ -154,6 +175,15 @@ static void WaitableTimerSignalHandler(int signum, siginfo_t* siginfo, void* arg
} }
} }
} }
static void WaitableTimerSignalHandler(int signum, siginfo_t* siginfo, void* arg)
{
WINPR_TIMER* timer = siginfo->si_value.sival_ptr;
if (!timer || (signum != SIGALRM))
return;
WaitableTimerHandler(timer);
}
static int InstallWaitableTimerSignalHandler(void) static int InstallWaitableTimerSignalHandler(void)
{ {
@ -173,7 +203,31 @@ static int InstallWaitableTimerSignalHandler(void)
#endif #endif
int InitializeWaitableTimer(WINPR_TIMER* timer) #if defined(__APPLE__)
static void WaitableTimerHandler(void* arg)
{
UINT64 data = 1;
WINPR_TIMER* timer = (WINPR_TIMER*)arg;
if (!timer)
return;
if (timer->pfnCompletionRoutine)
timer->pfnCompletionRoutine(timer->lpArgToCompletionRoutine, 0, 0);
if (write(timer->pipe[1], &data, sizeof(data)) != sizeof(data))
WLog_ERR(TAG, "failed to write to pipe");
if (timer->lPeriod == 0)
{
if (timer->running)
dispatch_suspend(timer->source);
timer->running = FALSE;
}
}
#endif
static int InitializeWaitableTimer(WINPR_TIMER* timer)
{ {
int result = 0; int result = 0;
@ -197,6 +251,7 @@ int InitializeWaitableTimer(WINPR_TIMER* timer)
return -1; return -1;
} }
#elif defined(__APPLE__)
#else #else
WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__); WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__);
result = -1; result = -1;
@ -218,6 +273,7 @@ int InitializeWaitableTimer(WINPR_TIMER* timer)
return -1; return -1;
} }
#elif defined(__APPLE__)
#else #else
WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__); WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__);
result = -1; result = -1;
@ -259,15 +315,49 @@ HANDLE CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManua
timer->lpArgToCompletionRoutine = NULL; timer->lpArgToCompletionRoutine = NULL;
timer->bInit = FALSE; timer->bInit = FALSE;
timer->ops = &ops; timer->ops = &ops;
#if defined(__APPLE__)
if (pipe(timer->pipe) != 0)
goto fail;
timer->queue = dispatch_queue_create(TAG, DISPATCH_QUEUE_SERIAL);
if (!timer->queue)
goto fail;
timer->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, timer->queue);
if (!timer->source)
goto fail;
dispatch_set_context(timer->source, timer);
dispatch_source_set_event_handler_f(timer->source, WaitableTimerHandler);
timer->fd = timer->pipe[0];
if (fcntl(timer->fd, F_SETFL, O_NONBLOCK) < 0)
goto fail;
#endif
} }
return handle; return handle;
fail:
TimerCloseHandle(handle);
return NULL;
} }
HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset,
LPCWSTR lpTimerName) LPCWSTR lpTimerName)
{ {
return NULL; int rc;
HANDLE handle;
LPSTR name = NULL;
rc = ConvertFromUnicode(CP_UTF8, 0, lpTimerName, -1, &name, 0, NULL, NULL);
if (rc < 0)
return NULL;
handle = CreateWaitableTimerA(lpTimerAttributes, bManualReset, name);
free(name);
return handle;
} }
HANDLE CreateWaitableTimerExA(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCSTR lpTimerName, HANDLE CreateWaitableTimerExA(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCSTR lpTimerName,
@ -281,7 +371,17 @@ HANDLE CreateWaitableTimerExA(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCSTR lp
HANDLE CreateWaitableTimerExW(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, HANDLE CreateWaitableTimerExW(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName,
DWORD dwFlags, DWORD dwDesiredAccess) DWORD dwFlags, DWORD dwDesiredAccess)
{ {
return NULL; int rc;
HANDLE handle;
LPSTR name = NULL;
rc = ConvertFromUnicode(CP_UTF8, 0, lpTimerName, -1, &name, 0, NULL, NULL);
if (rc < 0)
return NULL;
handle = CreateWaitableTimerExA(lpTimerAttributes, name, dwFlags, dwDesiredAccess);
free(name);
return handle;
} }
BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPeriod, BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPeriod,
@ -290,7 +390,7 @@ BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPerio
ULONG Type; ULONG Type;
WINPR_HANDLE* Object; WINPR_HANDLE* Object;
WINPR_TIMER* timer; WINPR_TIMER* timer;
#ifdef WITH_POSIX_TIMER #if defined(WITH_POSIX_TIMER) || defined(__APPLE__)
LONGLONG seconds = 0; LONGLONG seconds = 0;
LONGLONG nanoseconds = 0; LONGLONG nanoseconds = 0;
#ifdef HAVE_SYS_TIMERFD_H #ifdef HAVE_SYS_TIMERFD_H
@ -380,6 +480,44 @@ BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPerio
} }
} }
#elif defined(__APPLE__)
if (lpDueTime->QuadPart < 0)
{
LONGLONG due = lpDueTime->QuadPart * (-1);
/* due time is in 100 nanosecond intervals */
seconds = (due / 10000000);
nanoseconds = due * 100;
}
else if (lpDueTime->QuadPart == 0)
{
seconds = nanoseconds = 0;
}
else
{
WLog_ERR(TAG, "absolute time not implemented");
return FALSE;
}
{ /* Clean out old data from FD */
BYTE buffer[32];
while (read(timer->fd, buffer, sizeof(buffer)) > 0);
}
{
if (timer->running)
dispatch_suspend(timer->source);
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, nanoseconds);
uint64_t interval = DISPATCH_TIME_FOREVER;
if (lPeriod > 0)
interval = lPeriod * 1000000;
dispatch_source_set_timer(timer->source, start, interval, 0);
dispatch_resume(timer->source);
timer->running = TRUE;
}
#endif #endif
return TRUE; return TRUE;
} }
@ -388,18 +526,8 @@ BOOL SetWaitableTimerEx(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPer
PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext,
ULONG TolerableDelay) ULONG TolerableDelay)
{ {
ULONG Type; return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine,
WINPR_HANDLE* Object; FALSE);
if (!winpr_Handle_GetInfo(hTimer, &Type, &Object))
return FALSE;
(void)Object;
if (Type == HANDLE_TYPE_TIMER)
return TRUE;
return TRUE;
} }
HANDLE OpenWaitableTimerA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpTimerName) HANDLE OpenWaitableTimerA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpTimerName)
@ -414,6 +542,22 @@ HANDLE OpenWaitableTimerW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lp
BOOL CancelWaitableTimer(HANDLE hTimer) BOOL CancelWaitableTimer(HANDLE hTimer)
{ {
ULONG Type;
WINPR_HANDLE* Object;
WINPR_TIMER* timer;
if (!winpr_Handle_GetInfo(hTimer, &Type, &Object))
return FALSE;
if (Type != HANDLE_TYPE_TIMER)
return FALSE;
timer = (WINPR_TIMER*)Object;
#if defined(__APPLE__)
if (timer->running)
dispatch_suspend(timer->source);
timer->running = FALSE;
#endif
return TRUE; return TRUE;
} }
@ -426,14 +570,14 @@ BOOL CancelWaitableTimer(HANDLE hTimer)
* http://www.cs.wustl.edu/~schmidt/Timer_Queue.html * http://www.cs.wustl.edu/~schmidt/Timer_Queue.html
*/ */
void timespec_add_ms(struct timespec* tspec, UINT32 ms) static void timespec_add_ms(struct timespec* tspec, UINT32 ms)
{ {
UINT64 ns = tspec->tv_nsec + (ms * 1000000); UINT64 ns = tspec->tv_nsec + (ms * 1000000);
tspec->tv_sec += (ns / 1000000000); tspec->tv_sec += (ns / 1000000000);
tspec->tv_nsec = (ns % 1000000000); tspec->tv_nsec = (ns % 1000000000);
} }
UINT64 timespec_to_ms(struct timespec* tspec) static UINT64 timespec_to_ms(struct timespec* tspec)
{ {
UINT64 ms; UINT64 ms;
ms = tspec->tv_sec * 1000; ms = tspec->tv_sec * 1000;
@ -463,7 +607,7 @@ static void timespec_copy(struct timespec* dst, struct timespec* src)
dst->tv_nsec = src->tv_nsec; dst->tv_nsec = src->tv_nsec;
} }
void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) static void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer)
{ {
WINPR_TIMER_QUEUE_TIMER* node; WINPR_TIMER_QUEUE_TIMER* node;
@ -499,7 +643,7 @@ void InsertTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TI
} }
} }
void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer) static void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TIMER* timer)
{ {
BOOL found = FALSE; BOOL found = FALSE;
WINPR_TIMER_QUEUE_TIMER* node; WINPR_TIMER_QUEUE_TIMER* node;
@ -538,7 +682,7 @@ void RemoveTimerQueueTimer(WINPR_TIMER_QUEUE_TIMER** pHead, WINPR_TIMER_QUEUE_TI
} }
} }
int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) static int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue)
{ {
struct timespec CurrentTime; struct timespec CurrentTime;
WINPR_TIMER_QUEUE_TIMER* node; WINPR_TIMER_QUEUE_TIMER* node;
@ -616,7 +760,7 @@ static void* TimerQueueThread(void* arg)
return NULL; return NULL;
} }
int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue) static int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue)
{ {
pthread_cond_init(&(timerQueue->cond), NULL); pthread_cond_init(&(timerQueue->cond), NULL);
pthread_mutex_init(&(timerQueue->cond_mutex), NULL); pthread_mutex_init(&(timerQueue->cond_mutex), NULL);