summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/common/misc/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Runtime/common/misc/thread.cpp')
-rw-r--r--src/VBox/Runtime/common/misc/thread.cpp203
1 files changed, 136 insertions, 67 deletions
diff --git a/src/VBox/Runtime/common/misc/thread.cpp b/src/VBox/Runtime/common/misc/thread.cpp
index 5a61bd8ef..85a2cf114 100644
--- a/src/VBox/Runtime/common/misc/thread.cpp
+++ b/src/VBox/Runtime/common/misc/thread.cpp
@@ -1,4 +1,4 @@
-/* $Id: thread.cpp $ */
+/* $Id: thread.cpp 36951 2011-05-04 07:07:34Z vboxsync $ */
/** @file
* IPRT - Threads, common routines.
*/
@@ -83,13 +83,17 @@ static RTSEMRW g_ThreadRWSem = NIL_RTSEMRW;
/** The spinlocks protecting the tree. */
static RTSPINLOCK g_ThreadSpinlock = NIL_RTSPINLOCK;
#endif
+/** Indicates whether we've been initialized or not. */
+static bool g_frtThreadInitialized;
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
static void rtThreadDestroy(PRTTHREADINT pThread);
+#ifdef IN_RING3
static int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName);
+#endif
static void rtThreadRemoveLocked(PRTTHREADINT pThread);
static PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName);
@@ -126,7 +130,7 @@ static PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_
*
* @returns iprt status code.
*/
-int rtThreadInit(void)
+DECLHIDDEN(int) rtThreadInit(void)
{
#ifdef IN_RING3
int rc = VINF_ALREADY_INITIALIZED;
@@ -145,7 +149,10 @@ int rtThreadInit(void)
if (RT_SUCCESS(rc))
rc = rtSchedNativeCalcDefaultPriority(RTTHREADTYPE_DEFAULT);
if (RT_SUCCESS(rc))
+ {
+ g_frtThreadInitialized = true;
return VINF_SUCCESS;
+ }
/* failed, clear out */
RTSemRWDestroy(g_ThreadRWSem);
@@ -154,17 +161,20 @@ int rtThreadInit(void)
}
#elif defined(IN_RING0)
-
+ int rc;
/*
* Create the spinlock and to native init.
*/
Assert(g_ThreadSpinlock == NIL_RTSPINLOCK);
- int rc = RTSpinlockCreate(&g_ThreadSpinlock);
+ rc = RTSpinlockCreate(&g_ThreadSpinlock);
if (RT_SUCCESS(rc))
{
rc = rtThreadNativeInit();
if (RT_SUCCESS(rc))
+ {
+ g_frtThreadInitialized = true;
return VINF_SUCCESS;
+ }
/* failed, clear out */
RTSpinlockDestroy(g_ThreadSpinlock);
@@ -180,7 +190,7 @@ int rtThreadInit(void)
/**
* Terminates the thread database.
*/
-void rtThreadTerm(void)
+DECLHIDDEN(void) rtThreadTerm(void)
{
#ifdef IN_RING3
/* we don't cleanup here yet */
@@ -228,8 +238,6 @@ DECLINLINE(void) rtThreadUnLockRD(void)
AssertReleaseRC(rc);
}
-#endif /* IN_RING3 */
-
/**
* Adopts the calling thread.
@@ -237,6 +245,8 @@ DECLINLINE(void) rtThreadUnLockRD(void)
*/
static int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName)
{
+ int rc;
+ PRTTHREADINT pThread;
Assert(!(fFlags & RTTHREADFLAGS_WAITABLE));
fFlags &= ~RTTHREADFLAGS_WAITABLE;
@@ -245,8 +255,8 @@ static int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFla
* (It is vital that rtThreadNativeAdopt updates the TLS before
* we try inserting the thread because of locking.)
*/
- int rc = VERR_NO_MEMORY;
- PRTTHREADINT pThread = rtThreadAlloc(enmType, fFlags, RTTHREADINT_FLAGS_ALIEN | fIntFlags, pszName);
+ rc = VERR_NO_MEMORY;
+ pThread = rtThreadAlloc(enmType, fFlags, RTTHREADINT_FLAGS_ALIEN | fIntFlags, pszName);
if (pThread)
{
RTNATIVETHREAD NativeThread = RTThreadNativeSelf();
@@ -261,7 +271,6 @@ static int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFla
return rc;
}
-
/**
* Adopts a non-IPRT thread.
*
@@ -273,12 +282,15 @@ static int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFla
*/
RTDECL(int) RTThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, const char *pszName, PRTTHREAD pThread)
{
+ int rc;
+ RTTHREAD Thread;
+
AssertReturn(!(fFlags & RTTHREADFLAGS_WAITABLE), VERR_INVALID_PARAMETER);
AssertReturn(!pszName || VALID_PTR(pszName), VERR_INVALID_POINTER);
AssertReturn(!pThread || VALID_PTR(pThread), VERR_INVALID_POINTER);
- int rc = VINF_SUCCESS;
- RTTHREAD Thread = RTThreadSelf();
+ rc = VINF_SUCCESS;
+ Thread = RTThreadSelf();
if (Thread == NIL_RTTHREAD)
{
/* generate a name if none was given. */
@@ -323,6 +335,7 @@ RTDECL(RTTHREAD) RTThreadSelfAutoAdopt(void)
}
RT_EXPORT_SYMBOL(RTThreadSelfAutoAdopt);
+#endif /* IN_RING3 */
/**
* Allocates a per thread data structure and initializes the basic fields.
@@ -340,9 +353,12 @@ PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntF
PRTTHREADINT pThread = (PRTTHREADINT)RTMemAllocZ(sizeof(RTTHREADINT));
if (pThread)
{
+ size_t cchName;
+ int rc;
+
pThread->Core.Key = (void*)NIL_RTTHREAD;
pThread->u32Magic = RTTHREADINT_MAGIC;
- size_t cchName = strlen(pszName);
+ cchName = strlen(pszName);
if (cchName >= RTTHREAD_NAME_LEN)
cchName = RTTHREAD_NAME_LEN - 1;
memcpy(pThread->szName, pszName, cchName);
@@ -360,7 +376,7 @@ PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntF
#ifdef RT_WITH_ICONV_CACHE
rtStrIconvCacheInit(pThread);
#endif
- int rc = RTSemEventMultiCreate(&pThread->EventUser);
+ rc = RTSemEventMultiCreate(&pThread->EventUser);
if (RT_SUCCESS(rc))
{
rc = RTSemEventMultiCreate(&pThread->EventTerminated);
@@ -383,55 +399,58 @@ PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntF
* @param pThread Pointer to thread structure allocated by rtThreadAlloc().
* @param NativeThread The native thread id.
*/
-void rtThreadInsert(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread)
+DECLHIDDEN(void) rtThreadInsert(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread)
{
Assert(pThread);
Assert(pThread->u32Magic == RTTHREADINT_MAGIC);
- RT_THREAD_LOCK_TMP(Tmp);
- RT_THREAD_LOCK_RW(Tmp);
-
- /*
- * Do not insert a terminated thread.
- *
- * This may happen if the thread finishes before the RTThreadCreate call
- * gets this far. Since the OS may quickly reuse the native thread ID
- * it should not be reinserted at this point.
- */
- if (rtThreadGetState(pThread) != RTTHREADSTATE_TERMINATED)
{
+ RT_THREAD_LOCK_TMP(Tmp);
+ RT_THREAD_LOCK_RW(Tmp);
+
/*
- * Before inserting we must check if there is a thread with this id
- * in the tree already. We're racing parent and child on insert here
- * so that the handle is valid in both ends when they return / start.
+ * Do not insert a terminated thread.
*
- * If it's not ourself we find, it's a dead alien thread and we will
- * unlink it from the tree. Alien threads will be released at this point.
+ * This may happen if the thread finishes before the RTThreadCreate call
+ * gets this far. Since the OS may quickly reuse the native thread ID
+ * it should not be reinserted at this point.
*/
- PRTTHREADINT pThreadOther = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
- if (pThreadOther != pThread)
+ if (rtThreadGetState(pThread) != RTTHREADSTATE_TERMINATED)
{
- /* remove dead alien if any */
- if (pThreadOther)
+ /*
+ * Before inserting we must check if there is a thread with this id
+ * in the tree already. We're racing parent and child on insert here
+ * so that the handle is valid in both ends when they return / start.
+ *
+ * If it's not ourself we find, it's a dead alien thread and we will
+ * unlink it from the tree. Alien threads will be released at this point.
+ */
+ PRTTHREADINT pThreadOther = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
+ if (pThreadOther != pThread)
{
- AssertMsg(pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN, ("%p:%s; %p:%s\n", pThread, pThread->szName, pThreadOther, pThreadOther->szName));
- ASMAtomicBitClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT);
- rtThreadRemoveLocked(pThreadOther);
- if (pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN)
+ bool fRc;
+ /* remove dead alien if any */
+ if (pThreadOther)
+ {
+ AssertMsg(pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN, ("%p:%s; %p:%s\n", pThread, pThread->szName, pThreadOther, pThreadOther->szName));
+ ASMAtomicBitClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT);
+ rtThreadRemoveLocked(pThreadOther);
+ if (pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN)
rtThreadRelease(pThreadOther);
- }
+ }
- /* insert the thread */
- ASMAtomicWritePtr(&pThread->Core.Key, (void *)NativeThread);
- bool fRc = RTAvlPVInsert(&g_ThreadTree, &pThread->Core);
- ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE);
+ /* insert the thread */
+ ASMAtomicWritePtr(&pThread->Core.Key, (void *)NativeThread);
+ fRc = RTAvlPVInsert(&g_ThreadTree, &pThread->Core);
+ ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE);
- AssertReleaseMsg(fRc, ("Lock problem? %p (%RTnthrd) %s\n", pThread, NativeThread, pThread->szName));
- NOREF(fRc);
+ AssertReleaseMsg(fRc, ("Lock problem? %p (%RTnthrd) %s\n", pThread, NativeThread, pThread->szName));
+ NOREF(fRc);
+ }
}
- }
- RT_THREAD_UNLOCK_RW(Tmp);
+ RT_THREAD_UNLOCK_RW(Tmp);
+ }
}
@@ -486,14 +505,15 @@ DECLINLINE(bool) rtThreadIsAlive(PRTTHREADINT pThread)
* @returns NULL if not a thread IPRT knows.
* @param NativeThread The native thread id.
*/
-PRTTHREADINT rtThreadGetByNative(RTNATIVETHREAD NativeThread)
+DECLHIDDEN(PRTTHREADINT) rtThreadGetByNative(RTNATIVETHREAD NativeThread)
{
+ PRTTHREADINT pThread;
/*
* Simple tree lookup.
*/
RT_THREAD_LOCK_TMP(Tmp);
RT_THREAD_LOCK_RD(Tmp);
- PRTTHREADINT pThread = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
+ pThread = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
RT_THREAD_UNLOCK_RD(Tmp);
return pThread;
}
@@ -507,7 +527,7 @@ PRTTHREADINT rtThreadGetByNative(RTNATIVETHREAD NativeThread)
* @returns NULL if Thread was not found.
* @param Thread Thread id which structure is to be returned.
*/
-PRTTHREADINT rtThreadGet(RTTHREAD Thread)
+DECLHIDDEN(PRTTHREADINT) rtThreadGet(RTTHREAD Thread)
{
if ( Thread != NIL_RTTHREAD
&& VALID_PTR(Thread))
@@ -531,10 +551,11 @@ PRTTHREADINT rtThreadGet(RTTHREAD Thread)
* @returns New reference count.
* @param pThread The thread structure to release.
*/
-uint32_t rtThreadRelease(PRTTHREADINT pThread)
+DECLHIDDEN(uint32_t) rtThreadRelease(PRTTHREADINT pThread)
{
- Assert(pThread);
uint32_t cRefs;
+
+ Assert(pThread);
if (pThread->cRefs >= 1)
{
cRefs = ASMAtomicDecU32(&pThread->cRefs);
@@ -557,6 +578,7 @@ uint32_t rtThreadRelease(PRTTHREADINT pThread)
*/
static void rtThreadDestroy(PRTTHREADINT pThread)
{
+ RTSEMEVENTMULTI hEvt1, hEvt2;
/*
* Remove it from the tree and mark it as dead.
*
@@ -587,9 +609,9 @@ static void rtThreadDestroy(PRTTHREADINT pThread)
ASMAtomicXchgU32(&pThread->u32Magic, RTTHREADINT_MAGIC_DEAD);
ASMAtomicWritePtr(&pThread->Core.Key, (void *)NIL_RTTHREAD);
pThread->enmType = RTTHREADTYPE_INVALID;
- RTSEMEVENTMULTI hEvt1 = pThread->EventUser;
+ hEvt1 = pThread->EventUser;
pThread->EventUser = NIL_RTSEMEVENTMULTI;
- RTSEMEVENTMULTI hEvt2 = pThread->EventTerminated;
+ hEvt2 = pThread->EventTerminated;
pThread->EventTerminated = NIL_RTSEMEVENTMULTI;
#ifdef IN_RING3
@@ -615,7 +637,7 @@ static void rtThreadDestroy(PRTTHREADINT pThread)
* @param pThread The thread structure.
* @param rc The thread result code.
*/
-void rtThreadTerminate(PRTTHREADINT pThread, int rc)
+DECLHIDDEN(void) rtThreadTerminate(PRTTHREADINT pThread, int rc)
{
Assert(pThread->cRefs >= 1);
@@ -654,8 +676,9 @@ void rtThreadTerminate(PRTTHREADINT pThread, int rc)
* @param NativeThread The native thread id.
* @param pszThreadName The name of the thread (purely a dummy for backtrace).
*/
-int rtThreadMain(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread, const char *pszThreadName)
+DECLHIDDEN(int) rtThreadMain(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread, const char *pszThreadName)
{
+ int rc;
NOREF(pszThreadName);
rtThreadInsert(pThread, NativeThread);
Log(("rtThreadMain: Starting: pThread=%p NativeThread=%RTnthrd Name=%s pfnThread=%p pvUser=%p\n",
@@ -664,7 +687,7 @@ int rtThreadMain(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread, const char *
/*
* Change the priority.
*/
- int rc = rtThreadNativeSetPriority(pThread, pThread->enmType);
+ rc = rtThreadNativeSetPriority(pThread, pThread->enmType);
#ifdef IN_RING3
AssertMsgRC(rc, ("Failed to set priority of thread %p (%RTnthrd / %s) to enmType=%d enmPriority=%d rc=%Rrc\n",
pThread, NativeThread, pThread->szName, pThread->enmType, g_enmProcessPriority, rc));
@@ -713,6 +736,9 @@ int rtThreadMain(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread, const char *
RTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
RTTHREADTYPE enmType, unsigned fFlags, const char *pszName)
{
+ int rc;
+ PRTTHREADINT pThreadInt;
+
LogFlow(("RTThreadCreate: pThread=%p pfnThread=%p pvUser=%p cbStack=%#x enmType=%d fFlags=%#x pszName=%p:{%s}\n",
pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszName, pszName));
@@ -743,15 +769,15 @@ RTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUse
/*
* Allocate thread argument.
*/
- int rc;
- PRTTHREADINT pThreadInt = rtThreadAlloc(enmType, fFlags, 0, pszName);
+ pThreadInt = rtThreadAlloc(enmType, fFlags, 0, pszName);
if (pThreadInt)
{
+ RTNATIVETHREAD NativeThread;
+
pThreadInt->pfnThread = pfnThread;
pThreadInt->pvUser = pvUser;
pThreadInt->cbStack = cbStack;
- RTNATIVETHREAD NativeThread;
rc = rtThreadNativeCreate(pThreadInt, &NativeThread);
if (RT_SUCCESS(rc))
{
@@ -819,8 +845,9 @@ RTDECL(int) RTThreadCreateF(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUs
RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, ...)
{
va_list va;
+ int rc;
va_start(va, pszNameFmt);
- int rc = RTThreadCreateV(pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszNameFmt, va);
+ rc = RTThreadCreateV(pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszNameFmt, va);
va_end(va);
return rc;
}
@@ -897,9 +924,10 @@ RT_EXPORT_SYMBOL(RTThreadSelfName);
*/
RTDECL(const char *) RTThreadGetName(RTTHREAD Thread)
{
+ PRTTHREADINT pThread;
if (Thread == NIL_RTTHREAD)
return NULL;
- PRTTHREADINT pThread = rtThreadGet(Thread);
+ pThread = rtThreadGet(Thread);
if (pThread)
{
const char *szName = pThread->szName;
@@ -923,13 +951,14 @@ RTDECL(int) RTThreadSetName(RTTHREAD Thread, const char *pszName)
/*
* Validate input.
*/
+ PRTTHREADINT pThread;
size_t cchName = strlen(pszName);
if (cchName >= RTTHREAD_NAME_LEN)
{
AssertMsgFailed(("pszName=%s is too long, max is %d\n", pszName, RTTHREAD_NAME_LEN - 1));
return VERR_INVALID_PARAMETER;
}
- PRTTHREADINT pThread = rtThreadGet(Thread);
+ pThread = rtThreadGet(Thread);
if (!pThread)
return VERR_INVALID_HANDLE;
@@ -970,6 +999,47 @@ RTDECL(bool) RTThreadIsMain(RTTHREAD hThread)
RT_EXPORT_SYMBOL(RTThreadIsMain);
+RTDECL(bool) RTThreadIsSelfAlive(void)
+{
+ if (g_frtThreadInitialized)
+ {
+ RTTHREAD hSelf = RTThreadSelf();
+ if (hSelf != NIL_RTTHREAD)
+ {
+ /*
+ * Inspect the thread state. ASSUMES thread state order.
+ */
+ RTTHREADSTATE enmState = rtThreadGetState(hSelf);
+ if ( enmState >= RTTHREADSTATE_RUNNING
+ && enmState <= RTTHREADSTATE_END)
+ return true;
+ }
+ }
+ return false;
+}
+RT_EXPORT_SYMBOL(RTThreadIsSelfAlive);
+
+
+RTDECL(bool) RTThreadIsSelfKnown(void)
+{
+ if (g_frtThreadInitialized)
+ {
+ RTTHREAD hSelf = RTThreadSelf();
+ if (hSelf != NIL_RTTHREAD)
+ return true;
+ }
+ return false;
+}
+RT_EXPORT_SYMBOL(RTThreadIsSelfKnown);
+
+
+RTDECL(bool) RTThreadIsInitialized(void)
+{
+ return g_frtThreadInitialized;
+}
+RT_EXPORT_SYMBOL(RTThreadIsInitialized);
+
+
/**
* Signal the user event.
*
@@ -1270,7 +1340,7 @@ static DECLCALLBACK(int) rtThreadSetPriorityOne(PAVLPVNODECORE pNode, void *pvUs
* @returns iprt status code.
* @param enmPriority The new priority.
*/
-int rtThreadDoSetProcPriority(RTPROCPRIORITY enmPriority)
+DECLHIDDEN(int) rtThreadDoSetProcPriority(RTPROCPRIORITY enmPriority)
{
LogFlow(("rtThreadDoSetProcPriority: enmPriority=%d\n", enmPriority));
@@ -1452,7 +1522,7 @@ static DECLCALLBACK(int) rtThreadClearTlsEntryCallback(PAVLPVNODECORE pNode, voi
*
* @param iTls The TLS entry. (valid)
*/
-void rtThreadClearTlsEntry(RTTLS iTls)
+DECLHIDDEN(void) rtThreadClearTlsEntry(RTTLS iTls)
{
RT_THREAD_LOCK_TMP(Tmp);
RT_THREAD_LOCK_RD(Tmp);
@@ -1461,4 +1531,3 @@ void rtThreadClearTlsEntry(RTTLS iTls)
}
#endif /* IPRT_WITH_GENERIC_TLS */
-