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

View File

@ -1521,7 +1521,7 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
}
settings = context->settings;
timer = CreateWaitableTimerA(NULL, FALSE, NULL);
timer = CreateWaitableTimerA(NULL, FALSE, "mainloop-periodic-timer");
if (!timer)
{
@ -1581,7 +1581,7 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
nCount += tmp;
}
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 100);
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (waitStatus == WAIT_FAILED)
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();
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;
}
BOOL freerdp_parse_username(char* username, char** user, char** domain)
BOOL freerdp_parse_username(const char* username, char** user, char** domain)
{
char* p;
int length = 0;
@ -871,7 +871,7 @@ BOOL freerdp_parse_username(char* username, char** user, char** domain)
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;
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(
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_hostname(char* hostname, char** host, int* port);
FREERDP_API BOOL freerdp_parse_username(const char* username, char** user, char** domain);
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_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)
MINOR_VERSION=$(echo $VERSION | cut -d'.' -f2)
if [ "$MAJOR_VERSION" -lt "2" ]; then
if [ "$MAJOR_VERSION" -lt "2" ];
then
echo "Your version of astyle($VERSION) is too old, need at least 2.03"
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
if [ "$MINOR_VERSION" -lt "3" ]; then
echo "Your version of astyle($VERSION) is too old, need at least 2.03"
exit 1
fi
if [ $# -le 0 ]; then

View File

@ -34,6 +34,12 @@
#include <unistd.h>
#endif
#if defined(__APPLE__)
#include <mach/task.h>
#include <mach/mach.h>
#include <mach/semaphore.h>
#endif
#ifndef _WIN32
#include "../log.h"
@ -44,7 +50,8 @@ VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
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
@ -67,18 +74,24 @@ BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwS
lpCriticalSection->RecursionCount = 0;
lpCriticalSection->OwningThread = NULL;
lpCriticalSection->LockSemaphore = (winpr_sem_t*) malloc(sizeof(winpr_sem_t));
if (!lpCriticalSection->LockSemaphore)
return FALSE;
#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;
#else
if (sem_init(lpCriticalSection->LockSemaphore, 0, 0) != 0)
goto out_fail;
#endif
SetCriticalSectionSpinCount(lpCriticalSection, dwSpinCount);
return TRUE;
out_fail:
free(lpCriticalSection->LockSemaphore);
return FALSE;

View File

@ -86,6 +86,10 @@ typedef struct winpr_event WINPR_EVENT;
#include <sys/timerfd.h>
#endif
#if defined(__APPLE__)
#include <dispatch/dispatch.h>
#endif
struct winpr_timer
{
WINPR_HANDLE_DEF();
@ -101,6 +105,12 @@ struct winpr_timer
timer_t tid;
struct itimerspec timeout;
#endif
#if defined(__APPLE__)
dispatch_queue_t queue;
dispatch_source_t source;
int pipe[2];
BOOL running;
#endif
};
typedef struct winpr_timer WINPR_TIMER;

View File

@ -9,7 +9,6 @@ int TestSynchWaitableTimer(int argc, char* argv[])
LONG period;
LARGE_INTEGER due;
int result = -1;
timer = CreateWaitableTimer(NULL, FALSE, NULL);
if (!timer)
@ -35,17 +34,16 @@ int TestSynchWaitableTimer(int argc, char* argv[])
}
printf("Timer Signaled\n");
status = WaitForSingleObject(timer, 2000);
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;
}
due.QuadPart = 0;
period = 1200; /* 1.2 seconds */
if (!SetWaitableTimer(timer, &due, period, NULL, NULL, 0))
@ -62,6 +60,12 @@ int TestSynchWaitableTimer(int argc, char* argv[])
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)
{
printf("WaitForMultipleObjects(timer, INFINITE) failure\n");
@ -69,28 +73,9 @@ int TestSynchWaitableTimer(int argc, char* argv[])
}
printf("Timer Signaled\n");
result = 0;
out:
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;
}

View File

@ -12,7 +12,7 @@ struct 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;
UINT32 CurrentTime = GetTickCount();
@ -108,20 +108,6 @@ cleanup:
CloseHandle(g_Event);
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;
}

View File

@ -77,15 +77,25 @@ static DWORD TimerCleanupHandle(HANDLE handle)
if (!TimerIsHandled(handle))
return WAIT_FAILED;
if (timer->bManualReset)
return WAIT_OBJECT_0;
length = read(timer->fd, (void*) &expirations, sizeof(UINT64));
if (length != 8)
{
if (length == -1)
{
if (errno == ETIMEDOUT)
switch (errno)
{
case ETIMEDOUT:
case EAGAIN:
return WAIT_TIMEOUT;
default:
break;
}
WLog_ERR(TAG, "timer read() failure [%d] %s", errno, strerror(errno));
}
else
@ -123,6 +133,17 @@ BOOL TimerCloseHandle(HANDLE handle)
#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);
return TRUE;
}
@ -131,11 +152,11 @@ BOOL TimerCloseHandle(HANDLE handle)
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;
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)
{
@ -173,7 +203,31 @@ static int InstallWaitableTimerSignalHandler(void)
#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;
@ -197,6 +251,7 @@ int InitializeWaitableTimer(WINPR_TIMER* timer)
return -1;
}
#elif defined(__APPLE__)
#else
WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__);
result = -1;
@ -218,6 +273,7 @@ int InitializeWaitableTimer(WINPR_TIMER* timer)
return -1;
}
#elif defined(__APPLE__)
#else
WLog_ERR(TAG, "%s: os specific implementation is missing", __FUNCTION__);
result = -1;
@ -259,15 +315,49 @@ HANDLE CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManua
timer->lpArgToCompletionRoutine = NULL;
timer->bInit = FALSE;
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;
fail:
TimerCloseHandle(handle);
return NULL;
}
HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset,
LPCWSTR lpTimerName)
{
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,
@ -281,7 +371,17 @@ HANDLE CreateWaitableTimerExA(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCSTR lp
HANDLE CreateWaitableTimerExW(LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName,
DWORD dwFlags, DWORD dwDesiredAccess)
{
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,
@ -290,7 +390,7 @@ BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPerio
ULONG Type;
WINPR_HANDLE* Object;
WINPR_TIMER* timer;
#ifdef WITH_POSIX_TIMER
#if defined(WITH_POSIX_TIMER) || defined(__APPLE__)
LONGLONG seconds = 0;
LONGLONG nanoseconds = 0;
#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
return TRUE;
}
@ -388,18 +526,8 @@ BOOL SetWaitableTimerEx(HANDLE hTimer, const LARGE_INTEGER* lpDueTime, LONG lPer
PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext,
ULONG TolerableDelay)
{
ULONG Type;
WINPR_HANDLE* Object;
if (!winpr_Handle_GetInfo(hTimer, &Type, &Object))
return FALSE;
(void)Object;
if (Type == HANDLE_TYPE_TIMER)
return TRUE;
return TRUE;
return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine,
FALSE);
}
HANDLE OpenWaitableTimerA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpTimerName)
@ -414,6 +542,22 @@ HANDLE OpenWaitableTimerW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lp
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;
}
@ -426,14 +570,14 @@ BOOL CancelWaitableTimer(HANDLE hTimer)
* 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);
tspec->tv_sec += (ns / 1000000000);
tspec->tv_nsec = (ns % 1000000000);
}
UINT64 timespec_to_ms(struct timespec* tspec)
static UINT64 timespec_to_ms(struct timespec* tspec)
{
UINT64 ms;
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;
}
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;
@ -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;
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;
WINPR_TIMER_QUEUE_TIMER* node;
@ -616,7 +760,7 @@ static void* TimerQueueThread(void* arg)
return NULL;
}
int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue)
static int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue)
{
pthread_cond_init(&(timerQueue->cond), NULL);
pthread_mutex_init(&(timerQueue->cond_mutex), NULL);