summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/synch/sleep.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--winpr/libwinpr/synch/sleep.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/winpr/libwinpr/synch/sleep.c b/winpr/libwinpr/synch/sleep.c
new file mode 100644
index 0000000..be2f4c6
--- /dev/null
+++ b/winpr/libwinpr/synch/sleep.c
@@ -0,0 +1,148 @@
+/**
+ * WinPR: Windows Portable Runtime
+ * Synchronization Functions
+ *
+ * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <winpr/config.h>
+
+#include <winpr/platform.h>
+#include <winpr/windows.h>
+
+#include <winpr/synch.h>
+
+#include "../log.h"
+#include "../thread/apc.h"
+#include "../thread/thread.h"
+#include "../synch/pollset.h"
+
+#define TAG WINPR_TAG("synch.sleep")
+
+#ifndef _WIN32
+
+#include <time.h>
+
+WINPR_PRAGMA_DIAG_PUSH
+WINPR_PRAGMA_DIAG_IGNORED_RESERVED_ID_MACRO
+
+#ifdef WINPR_HAVE_UNISTD_H
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 500
+#endif
+#include <unistd.h>
+#endif
+
+WINPR_PRAGMA_DIAG_POP
+
+VOID Sleep(DWORD dwMilliseconds)
+{
+ usleep(dwMilliseconds * 1000);
+}
+
+DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable)
+{
+ WINPR_THREAD* thread = winpr_GetCurrentThread();
+ WINPR_POLL_SET pollset;
+ int status = 0;
+ DWORD ret = WAIT_FAILED;
+ BOOL autoSignalled = 0;
+
+ if (thread)
+ {
+ /* treat re-entrancy if a completion is calling us */
+ if (thread->apc.treatingCompletions)
+ bAlertable = FALSE;
+ }
+ else
+ {
+ /* called from a non WinPR thread */
+ bAlertable = FALSE;
+ }
+
+ if (!bAlertable || !thread->apc.length)
+ {
+ usleep(dwMilliseconds * 1000);
+ return 0;
+ }
+
+ if (!pollset_init(&pollset, thread->apc.length))
+ {
+ WLog_ERR(TAG, "unable to initialize pollset");
+ return WAIT_FAILED;
+ }
+
+ if (!apc_collectFds(thread, &pollset, &autoSignalled))
+ {
+ WLog_ERR(TAG, "unable to APC file descriptors");
+ goto out;
+ }
+
+ if (!autoSignalled)
+ {
+ /* we poll and wait only if no APC member is ready */
+ status = pollset_poll(&pollset, dwMilliseconds);
+ if (status < 0)
+ {
+ WLog_ERR(TAG, "polling of apc fds failed");
+ goto out;
+ }
+ }
+
+ if (apc_executeCompletions(thread, &pollset, 0))
+ {
+ ret = WAIT_IO_COMPLETION;
+ }
+ else
+ {
+ /* according to the spec return value is 0 see
+ * https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleepex*/
+ ret = 0;
+ }
+out:
+ pollset_uninit(&pollset);
+ return ret;
+}
+
+#endif
+
+VOID USleep(DWORD dwMicroseconds)
+{
+#ifndef _WIN32
+ usleep(dwMicroseconds);
+#else
+ static LARGE_INTEGER freq = { 0 };
+ LARGE_INTEGER t1 = { 0 };
+ LARGE_INTEGER t2 = { 0 };
+
+ QueryPerformanceCounter(&t1);
+
+ if (freq.QuadPart == 0)
+ {
+ QueryPerformanceFrequency(&freq);
+ }
+
+ // in order to save cpu cyles we use Sleep() for the large share ...
+ if (dwMicroseconds >= 1000)
+ {
+ Sleep(dwMicroseconds / 1000);
+ }
+ // ... and busy loop until all the requested micro seconds have passed
+ do
+ {
+ QueryPerformanceCounter(&t2);
+ } while (((t2.QuadPart - t1.QuadPart) * 1000000) / freq.QuadPart < dwMicroseconds);
+#endif
+}