Added WaitableTimer implementation for mac OS.
This commit is contained in:
parent
14997f96e3
commit
9bd13c25c9
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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, ':');
|
||||||
|
@ -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);
|
||||||
|
@ -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 $?
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user