summaryrefslogtreecommitdiffstats
path: root/src/VBox/Runtime/r3/os2/thread-os2.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/VBox/Runtime/r3/os2/thread-os2.cpp320
1 files changed, 320 insertions, 0 deletions
diff --git a/src/VBox/Runtime/r3/os2/thread-os2.cpp b/src/VBox/Runtime/r3/os2/thread-os2.cpp
new file mode 100644
index 00000000..28cab659
--- /dev/null
+++ b/src/VBox/Runtime/r3/os2/thread-os2.cpp
@@ -0,0 +1,320 @@
+/* $Id: thread-os2.cpp $ */
+/** @file
+ * IPRT - Threads, OS/2.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_THREAD
+#define INCL_BASE
+#include <os2.h>
+#undef RT_MAX
+
+#include <errno.h>
+#include <process.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <InnoTekLIBC/FastInfoBlocks.h>
+#include <InnoTekLIBC/thread.h>
+
+#include <iprt/thread.h>
+#include <iprt/log.h>
+#include <iprt/assert.h>
+#include <iprt/alloc.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/cpuset.h>
+#include <iprt/string.h>
+#include <iprt/err.h>
+#include "internal/thread.h"
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Pointer to thread local memory which points to the current thread. */
+static PRTTHREADINT *g_ppCurThread;
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+static void rtThreadNativeMain(void *pvArgs);
+
+
+DECLHIDDEN(int) rtThreadNativeInit(void)
+{
+ /*
+ * Allocate thread local memory.
+ */
+ PULONG pul;
+ int rc = DosAllocThreadLocalMemory(1, &pul);
+ if (rc)
+ return VERR_NO_TLS_FOR_SELF;
+ g_ppCurThread = (PRTTHREADINT *)(void *)pul;
+ return VINF_SUCCESS;
+}
+
+
+static void rtThreadOs2BlockSigAlarm(void)
+{
+ /*
+ * Block SIGALRM - required for timer-posix.cpp.
+ * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
+ * It will not help much if someone creates threads directly using pthread_create. :/
+ */
+ sigset_t SigSet;
+ sigemptyset(&SigSet);
+ sigaddset(&SigSet, SIGALRM);
+ sigprocmask(SIG_BLOCK, &SigSet, NULL);
+}
+
+
+DECLHIDDEN(void) rtThreadNativeReInitObtrusive(void)
+{
+ rtThreadOs2BlockSigAlarm();
+}
+
+
+DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
+{
+
+ *g_ppCurThread = pThread;
+ return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
+{
+ if (pThread == *g_ppCurThread)
+ *g_ppCurThread = NULL;
+}
+
+
+/**
+ * Wrapper which unpacks the params and calls thread function.
+ */
+static void rtThreadNativeMain(void *pvArgs)
+{
+ rtThreadOs2BlockSigAlarm();
+
+ /*
+ * Call common main.
+ */
+ PRTTHREADINT pThread = (PRTTHREADINT)pvArgs;
+ *g_ppCurThread = pThread;
+
+#ifdef fibGetTidPid
+ rtThreadMain(pThread, fibGetTidPid(), &pThread->szName[0]);
+#else
+ rtThreadMain(pThread, _gettid(), &pThread->szName[0]);
+#endif
+
+ *g_ppCurThread = NULL;
+ _endthread();
+}
+
+
+DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
+{
+ /*
+ * Default stack size.
+ */
+ if (!pThread->cbStack)
+ pThread->cbStack = 512*1024;
+
+ /*
+ * Create the thread.
+ */
+ int iThreadId = _beginthread(rtThreadNativeMain, NULL, pThread->cbStack, pThread);
+ if (iThreadId > 0)
+ {
+#ifdef fibGetTidPid
+ *pNativeThread = iThreadId | (fibGetPid() << 16);
+#else
+ *pNativeThread = iThreadId;
+#endif
+ return VINF_SUCCESS;
+ }
+ return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(RTTHREAD) RTThreadSelf(void)
+{
+ PRTTHREADINT pThread = *g_ppCurThread;
+ if (pThread)
+ return (RTTHREAD)pThread;
+ /** @todo import alien threads? */
+ return NULL;
+}
+
+
+RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
+{
+#ifdef fibGetTidPid
+ return fibGetTidPid();
+#else
+ return _gettid();
+#endif
+}
+
+
+RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
+{
+ LogFlow(("RTThreadSleep: cMillies=%d\n", cMillies));
+ DosSleep(cMillies);
+ LogFlow(("RTThreadSleep: returning (cMillies=%d)\n", cMillies));
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies)
+{
+ DosSleep(cMillies);
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(bool) RTThreadYield(void)
+{
+ uint64_t u64TS = ASMReadTSC();
+ DosSleep(0);
+ u64TS = ASMReadTSC() - u64TS;
+ bool fRc = u64TS > 1750;
+ LogFlow(("RTThreadYield: returning %d (%llu ticks)\n", fRc, u64TS));
+ return fRc;
+}
+
+
+RTR3DECL(int) RTThreadGetAffinity(PRTCPUSET pCpuSet)
+{
+ union
+ {
+ uint64_t u64;
+ MPAFFINITY mpaff;
+ } u;
+
+ APIRET rc = DosQueryThreadAffinity(AFNTY_THREAD, &u.mpaff);
+ if (!rc)
+ {
+ RTCpuSetFromU64(pCpuSet, u.u64);
+ return VINF_SUCCESS;
+ }
+ return RTErrConvertFromOS2(rc);
+}
+
+
+RTR3DECL(int) RTThreadSetAffinity(PCRTCPUSET pCpuSet)
+{
+ union
+ {
+ uint64_t u64;
+ MPAFFINITY mpaff;
+ } u;
+ u.u64 = pCpuSet ? RTCpuSetToU64(pCpuSet) : UINT64_MAX;
+ int rc = DosSetThreadAffinity(&u.mpaff);
+ if (!rc)
+ return VINF_SUCCESS;
+ return RTErrConvertFromOS2(rc);
+}
+
+
+RTR3DECL(RTTLS) RTTlsAlloc(void)
+{
+ AssertCompile(NIL_RTTLS == -1);
+ return __libc_TLSAlloc();
+}
+
+
+RTR3DECL(int) RTTlsAllocEx(PRTTLS piTls, PFNRTTLSDTOR pfnDestructor)
+{
+ int rc;
+ int iTls = __libc_TLSAlloc();
+ if (iTls != -1)
+ {
+ if ( !pfnDestructor
+ || __libc_TLSDestructor(iTls, (void (*)(void *, int, unsigned))pfnDestructor, 0) != -1)
+ {
+ *piTls = iTls;
+ return VINF_SUCCESS;
+ }
+
+ rc = RTErrConvertFromErrno(errno);
+ __libc_TLSFree(iTls);
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+
+ *piTls = NIL_RTTLS;
+ return rc;
+}
+
+
+RTR3DECL(int) RTTlsFree(RTTLS iTls)
+{
+ if (iTls == NIL_RTTLS)
+ return VINF_SUCCESS;
+ if (__libc_TLSFree(iTls) != -1)
+ return VINF_SUCCESS;
+ return RTErrConvertFromErrno(errno);
+}
+
+
+RTR3DECL(void *) RTTlsGet(RTTLS iTls)
+{
+ return __libc_TLSGet(iTls);
+}
+
+
+RTR3DECL(int) RTTlsGetEx(RTTLS iTls, void **ppvValue)
+{
+ int rc = VINF_SUCCESS;
+ void *pv = __libc_TLSGet(iTls);
+ if (RT_UNLIKELY(!pv))
+ {
+ errno = 0;
+ pv = __libc_TLSGet(iTls);
+ if (!pv && errno)
+ rc = RTErrConvertFromErrno(errno);
+ }
+
+ *ppvValue = pv;
+ return rc;
+}
+
+
+RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue)
+{
+ if (__libc_TLSSet(iTls, pvValue) != -1)
+ return VINF_SUCCESS;
+ return RTErrConvertFromErrno(errno);
+}
+
+
+RTR3DECL(int) RTThreadGetExecutionTimeMilli(uint64_t *pKernelTime, uint64_t *pUserTime)
+{
+ return VERR_NOT_IMPLEMENTED;
+}