thread.cpp revision 8e342a5c34610667d2b554cb86f1dc2f38a5313c
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* $Id$ */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** @file
fa9e4066f08beec538e775443c5be79dd423fcabahrens * IPRT - Threads, common routines.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (C) 2006-2007 Sun Microsystems, Inc.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This file is part of VirtualBox Open Source Edition (OSE), as
fa9e4066f08beec538e775443c5be79dd423fcabahrens * available from http://www.virtualbox.org. This file is free software;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * you can redistribute it and/or modify it under the terms of the GNU
fa9e4066f08beec538e775443c5be79dd423fcabahrens * General Public License (GPL) as published by the Free Software
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Foundation, in version 2 as it comes in the "COPYING" file of the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file may alternatively be used under the terms
fa9e4066f08beec538e775443c5be79dd423fcabahrens * of the Common Development and Distribution License Version 1.0
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * VirtualBox OSE distribution, in which case the provisions of the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL are applicable instead of those of the GPL.
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You may elect to license modified versions of this file under the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * terms and conditions of either the GPL or the CDDL or both.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Clara, CA 95054 USA or visit http://www.sun.com if you need
fa9e4066f08beec538e775443c5be79dd423fcabahrens * additional information or have any questions.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*******************************************************************************
fa9e4066f08beec538e775443c5be79dd423fcabahrens* Header Files *
fa9e4066f08beec538e775443c5be79dd423fcabahrens*******************************************************************************/
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define LOG_GROUP RTLOGGROUP_THREAD
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <iprt/thread.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "internal/iprt.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/log.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/avl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/alloc.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/assert.h>
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks#include <iprt/lockvalidator.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/semaphore.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef IN_RING0
fa9e4066f08beec538e775443c5be79dd423fcabahrens# include <iprt/spinlock.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <iprt/asm.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/err.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <iprt/string.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "internal/magics.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "internal/thread.h"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include "internal/sched.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "internal/process.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*******************************************************************************
fa9e4066f08beec538e775443c5be79dd423fcabahrens* Defined Constants And Macros *
fa9e4066f08beec538e775443c5be79dd423fcabahrens*******************************************************************************/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING0
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define RT_THREAD_LOCK_TMP(Tmp) RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define RT_THREAD_LOCK_RW(Tmp) RTSpinlockAcquireNoInts(g_ThreadSpinlock, &(Tmp))
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define RT_THREAD_UNLOCK_RW(Tmp) RTSpinlockReleaseNoInts(g_ThreadSpinlock, &(Tmp))
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define RT_THREAD_LOCK_RD(Tmp) RTSpinlockAcquireNoInts(g_ThreadSpinlock, &(Tmp))
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define RT_THREAD_UNLOCK_RD(Tmp) RTSpinlockReleaseNoInts(g_ThreadSpinlock, &(Tmp))
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define RT_THREAD_LOCK_TMP(Tmp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens# define RT_THREAD_LOCK_RW(Tmp) rtThreadLockRW()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw# define RT_THREAD_UNLOCK_RW(Tmp) rtThreadUnLockRW()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw# define RT_THREAD_LOCK_RD(Tmp) rtThreadLockRD()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw# define RT_THREAD_UNLOCK_RD(Tmp) rtThreadUnLockRD()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*******************************************************************************
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw* Global Variables *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw*******************************************************************************/
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** The AVL thread containing the threads. */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic PAVLPVNODECORE g_ThreadTree;
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef IN_RING3
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** The RW lock protecting the tree. */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic RTSEMRW g_ThreadRWSem = NIL_RTSEMRW;
fa9e4066f08beec538e775443c5be79dd423fcabahrens#else
fa9e4066f08beec538e775443c5be79dd423fcabahrens/** The spinlocks protecting the tree. */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic RTSPINLOCK g_ThreadSpinlock = NIL_RTSPINLOCK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*******************************************************************************
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw* Internal Functions *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw*******************************************************************************/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void rtThreadDestroy(PRTTHREADINT pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void rtThreadRemoveLocked(PRTTHREADINT pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/** @page pg_rt_thread IPRT Thread Internals
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * IPRT provides interface to whatever native threading that the host provides,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * preferably using a CRT level interface to better integrate with other libraries.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Internally IPRT keeps track of threads by means of the RTTHREADINT structure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * All the RTTHREADINT structures are kept in a AVL tree which is protected by a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * read/write lock for efficient access. A thread is inserted into the tree in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * three places in the code. The main thread is 'adopted' by IPRT on RTR3Init()
fa9e4066f08beec538e775443c5be79dd423fcabahrens * by rtThreadAdopt(). When creating a new thread there the child and the parent
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * race inserting the thread, this is rtThreadMain() and RTThreadCreate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * RTTHREADINT objects are using reference counting as a mean of sticking around
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * till no-one needs them any longer. Waitable threads is created with one extra
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * reference so they won't go away until they are waited on. This introduces a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * major problem if we use the host thread identifier as key in the AVL tree - the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * host may reuse the thread identifier before the thread was waited on. So, on
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * most platforms we are using the RTTHREADINT pointer as key and not the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * thread id. RTThreadSelf() then have to be implemented using a pointer stored
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in thread local storage (TLS).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * In Ring-0 we only try keep track of kernel threads created by RTThreadCreate
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * at the moment. There we really only need the 'join' feature, but doing things
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the same way allow us to name threads and similar stuff.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Initializes the thread database.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint rtThreadInit(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = VINF_ALREADY_INITIALIZED;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (g_ThreadRWSem == NIL_RTSEMRW)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * We assume the caller is the 1st thread, which we'll call 'main'.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * But first, we'll create the semaphore.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = RTSemRWCreate(&g_ThreadRWSem);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = rtThreadNativeInit();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = rtThreadAdopt(RTTHREADTYPE_DEFAULT, 0, RTTHREADINT_FLAGS_MAIN, "main");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = rtSchedNativeCalcDefaultPriority(RTTHREADTYPE_DEFAULT);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* failed, clear out */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSemRWDestroy(g_ThreadRWSem);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw g_ThreadRWSem = NIL_RTSEMRW;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#elif defined(IN_RING0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Create the spinlock and to native init.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(g_ThreadSpinlock == NIL_RTSPINLOCK);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = RTSpinlockCreate(&g_ThreadSpinlock);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = rtThreadNativeInit();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* failed, clear out */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSpinlockDestroy(g_ThreadSpinlock);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw g_ThreadSpinlock = NIL_RTSPINLOCK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw# error "!IN_RING0 && !IN_RING3"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Terminates the thread database.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid rtThreadTerm(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* we don't cleanup here yet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#elif defined(IN_RING0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* just destroy the spinlock and assume the thread is fine... */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSpinlockDestroy(g_ThreadSpinlock);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw g_ThreadSpinlock = NIL_RTSPINLOCK;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (g_ThreadTree != NULL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTAssertMsg2Weak("WARNING: g_ThreadTree=%p\n", g_ThreadTree);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLINLINE(void) rtThreadLockRW(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (g_ThreadRWSem == NIL_RTSEMRW)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadInit();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = RTSemRWRequestWrite(g_ThreadRWSem, RT_INDEFINITE_WAIT);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReleaseRC(rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLINLINE(void) rtThreadLockRD(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (g_ThreadRWSem == NIL_RTSEMRW)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadInit();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = RTSemRWRequestRead(g_ThreadRWSem, RT_INDEFINITE_WAIT);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReleaseRC(rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLINLINE(void) rtThreadUnLockRW(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = RTSemRWReleaseWrite(g_ThreadRWSem);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReleaseRC(rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLINLINE(void) rtThreadUnLockRD(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = RTSemRWReleaseRead(g_ThreadRWSem);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReleaseRC(rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif /* IN_RING3 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Adopts the calling thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * No locks are taken or released by this function.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int rtThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(!(fFlags & RTTHREADFLAGS_WAITABLE));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw fFlags &= ~RTTHREADFLAGS_WAITABLE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Allocate and insert the thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * (It is vital that rtThreadNativeAdopt updates the TLS before
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * we try inserting the thread because of locking.)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = VERR_NO_MEMORY;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadAlloc(enmType, fFlags, RTTHREADINT_FLAGS_ALIEN | fIntFlags, pszName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTNATIVETHREAD NativeThread = RTThreadNativeSelf();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = rtThreadNativeAdopt(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadInsert(pThread, NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Adopts a non-IPRT thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns IPRT status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param enmType The thread type.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param fFlags The thread flags. RTTHREADFLAGS_WAITABLE is not currently allowed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pszName The thread name. Optional.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread Where to store the thread handle. Optional.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, const char *pszName, PRTTHREAD pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReturn(!(fFlags & RTTHREADFLAGS_WAITABLE), VERR_INVALID_PARAMETER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReturn(!pszName || VALID_PTR(pszName), VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReturn(!pThread || VALID_PTR(pThread), VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTTHREAD Thread = RTThreadSelf();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (Thread == NIL_RTTHREAD)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* generate a name if none was given. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char szName[RTTHREAD_NAME_LEN];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pszName || !*pszName)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw static uint32_t s_i32AlienId = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t i32Id = ASMAtomicIncU32(&s_i32AlienId);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTStrPrintf(szName, sizeof(szName), "ALIEN-%RX32", i32Id);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pszName = szName;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* try adopt it */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = rtThreadAdopt(enmType, fFlags, 0, pszName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Thread = RTThreadSelf();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Log(("RTThreadAdopt: %RTthrd %RTnthrd '%s' enmType=%d fFlags=%#x rc=%Rrc\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Thread, RTThreadNativeSelf(), pszName, enmType, fFlags, rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Log(("RTThreadAdopt: %RTthrd %RTnthrd '%s' enmType=%d fFlags=%#x - already adopted!\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Thread, RTThreadNativeSelf(), pszName, enmType, fFlags));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pThread = Thread;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadAdopt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the thread handle of the current thread, automatically adopting alien
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * threads.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns Thread handle.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(RTTHREAD) RTThreadSelfAutoAdopt(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTTHREAD hSelf = RTThreadSelf();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_UNLIKELY(hSelf == NIL_RTTHREAD))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTThreadAdopt(RTTHREADTYPE_DEFAULT, 0, NULL, &hSelf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return hSelf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadSelfAutoAdopt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Allocates a per thread data structure and initializes the basic fields.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns Pointer to per thread data structure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is reference once.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns NULL on failure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param enmType The thread type.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param fFlags The thread flags.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param fIntFlags The internal thread flags.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pszName Pointer to the thread name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
fa9e4066f08beec538e775443c5be79dd423fcabahrensPRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRTTHREADINT pThread = (PRTTHREADINT)RTMemAllocZ(sizeof(RTTHREADINT));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->Core.Key = (void*)NIL_RTTHREAD;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->u32Magic = RTTHREADINT_MAGIC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t cchName = strlen(pszName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (cchName >= RTTHREAD_NAME_LEN)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cchName = RTTHREAD_NAME_LEN - 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw memcpy(pThread->szName, pszName, cchName);
fa9e4066f08beec538e775443c5be79dd423fcabahrens pThread->szName[cchName] = '\0';
fa9e4066f08beec538e775443c5be79dd423fcabahrens pThread->cRefs = 2 + !!(fFlags & RTTHREADFLAGS_WAITABLE); /* And extra reference if waitable. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens pThread->rc = VERR_PROCESS_RUNNING; /** @todo get a better error code! */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->enmType = enmType;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->fFlags = fFlags;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->fIntFlags = fIntFlags;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->enmState = RTTHREADSTATE_INITIALIZING;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->fReallySleeping = false;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtLockValidatorInitPerThread(&pThread->LockValidator);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = RTSemEventMultiCreate(&pThread->EventUser);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = RTSemEventMultiCreate(&pThread->EventTerminated);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return pThread;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSemEventMultiDestroy(pThread->EventUser);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTMemFree(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Insert the per thread data structure into the tree.
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks *
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks * This can be called from both the thread it self and the parent,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * thus it must handle insertion failures in a nice manner.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread Pointer to thread structure allocated by rtThreadAlloc().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param NativeThread The native thread id.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid rtThreadInsert(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks Assert(pThread);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks Assert(pThread->u32Magic == RTTHREADINT_MAGIC);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_TMP(Tmp);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks RT_THREAD_LOCK_RW(Tmp);
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks /*
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks * Do not insert a terminated thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This may happen if the thread finishes before the RTThreadCreate call
fa9e4066f08beec538e775443c5be79dd423fcabahrens * gets this far. Since the OS may quickly reuse the native thread ID
fa9e4066f08beec538e775443c5be79dd423fcabahrens * it should not be reinserted at this point.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rtThreadGetState(pThread) != RTTHREADSTATE_TERMINATED)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Before inserting we must check if there is a thread with this id
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in the tree already. We're racing parent and child on insert here
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * so that the handle is valid in both ends when they return / start.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If it's not ourself we find, it's a dead alien thread and we will
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unlink it from the tree. Alien threads will be released at this point.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThreadOther = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThreadOther != pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* remove dead alien if any */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThreadOther)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsg(pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN, ("%p:%s; %p:%s\n", pThread, pThread->szName, pThreadOther, pThreadOther->szName));
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicBitClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT);
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks rtThreadRemoveLocked(pThreadOther);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThreadOther->fIntFlags & RTTHREADINT_FLAGS_ALIEN)
169cdae232f15e542d6af0a9ce30c3f84222bc0fmarks rtThreadRelease(pThreadOther);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* insert the thread */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicWritePtr(&pThread->Core.Key, (void *)NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fRc = RTAvlPVInsert(&g_ThreadTree, &pThread->Core);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertReleaseMsg(fRc, ("Lock problem? %p (%RTnthrd) %s\n", pThread, NativeThread, pThread->szName));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NOREF(fRc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_UNLOCK_RW(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Removes the thread from the AVL tree, call owns the tree lock
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and has cleared the RTTHREADINT_FLAG_IN_TREE bit.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread The thread to remove.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void rtThreadRemoveLocked(PRTTHREADINT pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread2 = (PRTTHREADINT)RTAvlPVRemove(&g_ThreadTree, pThread->Core.Key);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#if !defined(RT_OS_OS2) /** @todo this asserts for threads created by NSPR */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsg(pThread2 == pThread, ("%p(%s) != %p (%p/%s)\n", pThread2, pThread2 ? pThread2->szName : "<null>",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread, pThread->Core.Key, pThread->szName));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NOREF(pThread2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Removes the thread from the AVL tree.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread The thread to remove.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void rtThreadRemove(PRTTHREADINT pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_TMP(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_RW(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ASMAtomicBitTestAndClear(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRemoveLocked(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_UNLOCK_RW(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Checks if a thread is alive or not.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns true if the thread is alive (or we don't really know).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns false if the thread has surely terminate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwDECLINLINE(bool) rtThreadIsAlive(PRTTHREADINT pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return !(pThread->fIntFlags & RTTHREADINT_FLAGS_TERMINATED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Gets a thread by it's native ID.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns pointer to the thread structure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns NULL if not a thread IPRT knows.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param NativeThread The native thread id.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwPRTTHREADINT rtThreadGetByNative(RTNATIVETHREAD NativeThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Simple tree lookup.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_TMP(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_RD(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = (PRTTHREADINT)RTAvlPVGet(&g_ThreadTree, (void *)NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_UNLOCK_RD(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return pThread;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Gets the per thread data structure for a thread handle.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns Pointer to the per thread data structure for Thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The caller must release the thread using rtThreadRelease().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns NULL if Thread was not found.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param Thread Thread id which structure is to be returned.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwPRTTHREADINT rtThreadGet(RTTHREAD Thread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ( Thread != NIL_RTTHREAD
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw && VALID_PTR(Thread))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = (PRTTHREADINT)Thread;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ( pThread->u32Magic == RTTHREADINT_MAGIC
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw && pThread->cRefs > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicIncU32(&pThread->cRefs);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return pThread;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgFailed(("Thread=%RTthrd\n", Thread));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Release a per thread data structure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns New reference count.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread The thread structure to release.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwuint32_t rtThreadRelease(PRTTHREADINT pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t cRefs;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread->cRefs >= 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cRefs = ASMAtomicDecU32(&pThread->cRefs);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!cRefs)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadDestroy(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cRefs = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return cRefs;
4c841f6070b4f88f9dc008de526b313bbebd4e32marks}
4c841f6070b4f88f9dc008de526b313bbebd4e32marks
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
4c841f6070b4f88f9dc008de526b313bbebd4e32marks * Destroys the per thread data.
4c841f6070b4f88f9dc008de526b313bbebd4e32marks *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread The thread to destroy.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void rtThreadDestroy(PRTTHREADINT pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Remove it from the tree and mark it as dead.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Threads that has seen rtThreadTerminate and should already have been
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * removed from the tree. There is probably no thread that should
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * require removing here. However, be careful making sure that cRefs
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * isn't 0 if we do or we'll blow up because the strict locking code
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will be calling us back.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ASMBitTest(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicIncU32(&pThread->cRefs);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRemove(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicDecU32(&pThread->cRefs);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Invalidate the thread structure and free it.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtLockValidatorSerializeDestructEnter();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicXchgU32(&pThread->u32Magic, RTTHREADINT_MAGIC_DEAD);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicWritePtr(&pThread->Core.Key, (void *)NIL_RTTHREAD);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->enmType = RTTHREADTYPE_INVALID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSEMEVENTMULTI hEvt1 = pThread->EventUser;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->EventUser = NIL_RTSEMEVENTMULTI;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSEMEVENTMULTI hEvt2 = pThread->EventTerminated;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->EventTerminated = NIL_RTSEMEVENTMULTI;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTMemFree(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtLockValidatorSerializeDestructLeave();
bda89588bd7667394a834e8a9a34612cce2ae9c3jp#endif
bda89588bd7667394a834e8a9a34612cce2ae9c3jp
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Destroy semaphore resources.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSemEventMultiDestroy(hEvt1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (hEvt2 != NIL_RTSEMEVENTMULTI)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSemEventMultiDestroy(hEvt2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Terminates the thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Called by the thread wrapper function when the thread terminates.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread The thread structure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param rc The thread result code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid rtThreadTerminate(PRTTHREADINT pThread, int rc)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(pThread->cRefs >= 1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IPRT_WITH_GENERIC_TLS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Destroy TLS entries.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadTlsDestruction(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif /* IPRT_WITH_GENERIC_TLS */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Set the rc, mark it terminated and signal anyone waiting.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->rc = rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadSetState(pThread, RTTHREADSTATE_TERMINATED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAGS_TERMINATED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread->EventTerminated != NIL_RTSEMEVENTMULTI)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTSemEventMultiSignal(pThread->EventTerminated);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Remove the thread from the tree so that there will be no
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * key clashes in the AVL tree and release our reference to ourself.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks rtThreadRemove(pThread);
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks rtThreadRelease(pThread);
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks}
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks * The common thread main function.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is called by rtThreadNativeMain().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns The status code of the thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * pThread is dereference by the thread before returning!
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread The thread structure.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param NativeThread The native thread id.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pszThreadName The name of the thread (purely a dummy for backtrace).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint rtThreadMain(PRTTHREADINT pThread, RTNATIVETHREAD NativeThread, const char *pszThreadName)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NOREF(pszThreadName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadInsert(pThread, NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Log(("rtThreadMain: Starting: pThread=%p NativeThread=%RTnthrd Name=%s pfnThread=%p pvUser=%p\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread, NativeThread, pThread->szName, pThread->pfnThread, pThread->pvUser));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Change the priority.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = rtThreadNativeSetPriority(pThread, pThread->enmType);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgRC(rc, ("Failed to set priority of thread %p (%RTnthrd / %s) to enmType=%d enmPriority=%d rc=%Rrc\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread, NativeThread, pThread->szName, pThread->enmType, g_enmProcessPriority, rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgRC(rc, ("Failed to set priority of thread %p (%RTnthrd / %s) to enmType=%d rc=%Rrc\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread, NativeThread, pThread->szName, pThread->enmType, rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Call thread function and terminate when it returns.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = pThread->pfnThread(pThread, pThread->pvUser);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Paranoia checks for leftover resources.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef RTSEMRW_STRICT
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t cWrite = ASMAtomicReadS32(&pThread->cWriteLocks);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(!cWrite);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int32_t cRead = ASMAtomicReadS32(&pThread->cReadLocks);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(!cRead);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Log(("rtThreadMain: Terminating: rc=%d pThread=%p NativeThread=%RTnthrd Name=%s pfnThread=%p pvUser=%p\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc, pThread, NativeThread, pThread->szName, pThread->pfnThread, pThread->pvUser));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadTerminate(pThread, rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Create a new thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread Where to store the thread handle to the new thread. (optional)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pfnThread The thread function.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pvUser User argument.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param cbStack The size of the stack for the new thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use 0 for the default stack size.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param enmType The thread type. Used for deciding scheduling attributes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of the thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param fFlags Flags of the RTTHREADFLAGS type (ORed together).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pszName Thread name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTTHREADTYPE enmType, unsigned fFlags, const char *pszName)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlow(("RTThreadCreate: pThread=%p pfnThread=%p pvUser=%p cbStack=%#x enmType=%d fFlags=%#x pszName=%p:{%s}\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszName, pszName));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Validate input.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!VALID_PTR(pThread) && pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(VALID_PTR(pThread));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VERR_INVALID_PARAMETER;
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks }
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks if (!VALID_PTR(pfnThread))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks Assert(VALID_PTR(pfnThread));
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks return VERR_INVALID_PARAMETER;
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks }
2459a9eaca6b6525c76289d22ffe4c96be1956d6marks if (!pszName || !*pszName || strlen(pszName) >= RTTHREAD_NAME_LEN)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsgFailed(("pszName=%s (max len is %d because of logging)\n", pszName, RTTHREAD_NAME_LEN - 1));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_INVALID_PARAMETER;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (fFlags & ~RTTHREADFLAGS_MASK)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsgFailed(("fFlags=%#x\n", fFlags));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VERR_INVALID_PARAMETER;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Allocate thread argument.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThreadInt = rtThreadAlloc(enmType, fFlags, 0, pszName);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThreadInt)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens pThreadInt->pfnThread = pfnThread;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pThreadInt->pvUser = pvUser;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pThreadInt->cbStack = cbStack;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTNATIVETHREAD NativeThread;
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = rtThreadNativeCreate(pThreadInt, &NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadInsert(pThreadInt, NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThreadInt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Log(("RTThreadCreate: Created thread %p (%p) %s\n", pThreadInt, NativeThread, pszName));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pThread = pThreadInt;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThreadInt->cRefs = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThreadInt);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = VERR_NO_TMP_MEMORY;
bda89588bd7667394a834e8a9a34612cce2ae9c3jp LogFlow(("RTThreadCreate: Failed to create thread, rc=%Rrc\n", rc));
bda89588bd7667394a834e8a9a34612cce2ae9c3jp AssertReleaseRC(rc);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadCreate);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Create a new thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Same as RTThreadCreate except the name is given in the RTStrPrintfV form.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pThread See RTThreadCreate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pfnThread See RTThreadCreate.
29a0b7379cd3103841d05e3ed04486412049acccmarks * @param pvUser See RTThreadCreate.
29a0b7379cd3103841d05e3ed04486412049acccmarks * @param cbStack See RTThreadCreate.
29a0b7379cd3103841d05e3ed04486412049acccmarks * @param enmType See RTThreadCreate.
29a0b7379cd3103841d05e3ed04486412049acccmarks * @param fFlags See RTThreadCreate.
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks * @param pszNameFmt Thread name format.
29a0b7379cd3103841d05e3ed04486412049acccmarks * @param va Format arguments.
29a0b7379cd3103841d05e3ed04486412049acccmarks */
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marksRTDECL(int) RTThreadCreateV(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
e6032be1b8a5a1d03081e0d62b624db95c4cf8b7marks RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, va_list va)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char szName[RTTHREAD_NAME_LEN * 2];
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTStrPrintfV(szName, sizeof(szName), pszNameFmt, va);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return RTThreadCreate(pThread, pfnThread, pvUser, cbStack, enmType, fFlags, szName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadCreateV);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Create a new thread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Same as RTThreadCreate except the name is given in the RTStrPrintf form.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns iprt status code.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pThread See RTThreadCreate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pfnThread See RTThreadCreate.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pvUser See RTThreadCreate.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param cbStack See RTThreadCreate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param enmType See RTThreadCreate.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param fFlags See RTThreadCreate.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pszNameFmt Thread name format.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param ... Format arguments.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadCreateF(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, ...)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw va_list va;
fa9e4066f08beec538e775443c5be79dd423fcabahrens va_start(va, pszNameFmt);
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = RTThreadCreateV(pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszNameFmt, va);
fa9e4066f08beec538e775443c5be79dd423fcabahrens va_end(va);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadCreateF);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the native thread id of a IPRT thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns The native thread id.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param Thread The IPRT thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(RTNATIVETHREAD) RTThreadGetNative(RTTHREAD Thread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRTTHREADINT pThread = rtThreadGet(Thread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTNATIVETHREAD NativeThread = (RTNATIVETHREAD)pThread->Core.Key;
fa9e4066f08beec538e775443c5be79dd423fcabahrens rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return NativeThread;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return NIL_RTNATIVETHREAD;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadGetNative);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the IPRT thread of a native thread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns The IPRT thread handle
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns NIL_RTTHREAD if not a thread known to IPRT.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param NativeThread The native thread handle/id.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(RTTHREAD) RTThreadFromNative(RTNATIVETHREAD NativeThread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRTTHREADINT pThread = rtThreadGetByNative(NativeThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return pThread;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return NIL_RTTHREAD;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadFromNative);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the name of the current thread thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns Pointer to readonly name string.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns NULL on failure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(const char *) RTThreadSelfName(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTTHREAD Thread = RTThreadSelf();
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (Thread != NIL_RTTHREAD)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRTTHREADINT pThread = rtThreadGet(Thread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *szName = pThread->szName;
fa9e4066f08beec538e775443c5be79dd423fcabahrens rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return szName;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadSelfName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the name of a thread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns Pointer to readonly name string.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns NULL on failure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param Thread Thread handle of the thread to query the name of.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(const char *) RTThreadGetName(RTTHREAD Thread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (Thread == NIL_RTTHREAD)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(Thread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw const char *szName = pThread->szName;
bda89588bd7667394a834e8a9a34612cce2ae9c3jp rtThreadRelease(pThread);
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks return szName;
e0d35c4478bf9fd4080951b5b9d1f9a38948ba69marks }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadGetName);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Sets the name of a thread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param Thread Thread handle of the thread to query the name of.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pszName The thread name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadSetName(RTTHREAD Thread, const char *pszName)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Validate input.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t cchName = strlen(pszName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (cchName >= RTTHREAD_NAME_LEN)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertMsgFailed(("pszName=%s is too long, max is %d\n", pszName, RTTHREAD_NAME_LEN - 1));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VERR_INVALID_PARAMETER;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(Thread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VERR_INVALID_HANDLE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Update the name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThread->szName[cchName] = '\0'; /* paranoia */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw memcpy(pThread->szName, pszName, cchName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadSetName);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Checks if the specified thread is the main thread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns true if it is, false if it isn't.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * @param hThread The thread handle.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @remarks This function may not return the correct value when RTR3Init was
fa9e4066f08beec538e775443c5be79dd423fcabahrens * called on a thread of the than the main one. This could for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * instance happen when the DLL/DYLIB/SO containing IPRT is dynamically
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * loaded at run time by a different thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(bool) RTThreadIsMain(RTTHREAD hThread)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock{
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRTTHREADINT pThread = rtThreadGet(hThread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock bool fRc = !!(pThread->fIntFlags & RTTHREADINT_FLAGS_MAIN);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return fRc;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return false;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadIsMain);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Signal the user event.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadUserSignal(RTTHREAD Thread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(Thread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rc = RTSemEventMultiSignal(pThread->EventUser);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = VERR_INVALID_HANDLE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock}
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockRT_EXPORT_SYMBOL(RTThreadUserSignal);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Wait for the user event, resume on interruption.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns iprt status code.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param Thread The thread to wait for.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * an indefinite wait.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTThreadUserWait(RTTHREAD Thread, unsigned cMillies)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRTTHREADINT pThread = rtThreadGet(Thread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread)
bda89588bd7667394a834e8a9a34612cce2ae9c3jp {
bda89588bd7667394a834e8a9a34612cce2ae9c3jp rc = RTSemEventMultiWait(pThread->EventUser, cMillies);
fa9e4066f08beec538e775443c5be79dd423fcabahrens rtThreadRelease(pThread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = VERR_INVALID_HANDLE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadUserWait);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Wait for the user event, return on interruption.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns iprt status code.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param Thread The thread to wait for.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
bda89588bd7667394a834e8a9a34612cce2ae9c3jp * an indefinite wait.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTThreadUserWaitNoResume(RTTHREAD Thread, unsigned cMillies)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(Thread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = RTSemEventMultiWaitNoResume(pThread->EventUser, cMillies);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = VERR_INVALID_HANDLE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadUserWaitNoResume);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Reset the user event.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param Thread The thread to reset.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadUserReset(RTTHREAD Thread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(Thread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = RTSemEventMultiReset(pThread->EventUser);
fa9e4066f08beec538e775443c5be79dd423fcabahrens rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = VERR_INVALID_HANDLE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadUserReset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Wait for the thread to terminate.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param Thread The thread to wait for.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * an indefinite wait.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param prc Where to store the return code of the thread. Optional.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param fAutoResume Whether or not to resume the wait on VERR_INTERRUPTED.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int rtThreadWait(RTTHREAD Thread, unsigned cMillies, int *prc, bool fAutoResume)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = VERR_INVALID_HANDLE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (Thread != NIL_RTTHREAD)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
7106075a406fbb9356893d9b37bc3053be6071c1marks PRTTHREADINT pThread = rtThreadGet(Thread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pThread->fFlags & RTTHREADFLAGS_WAITABLE)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (fAutoResume)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = RTSemEventMultiWait(pThread->EventTerminated, cMillies);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = RTSemEventMultiWaitNoResume(pThread->EventTerminated, cMillies);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (prc)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *prc = pThread->rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
de122929e7c37df60cbea70616404e22d20e025bmarks /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the thread is marked as waitable, we'll do one additional
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * release in order to free up the thread structure (see how we
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * init cRef in rtThreadAlloc()).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ASMAtomicBitTestAndClear(&pThread->fFlags, RTTHREADFLAGS_WAITABLE_BIT))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
de122929e7c37df60cbea70616404e22d20e025bmarks rc = VERR_THREAD_NOT_WAITABLE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertRC(rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Wait for the thread to terminate, resume on interruption.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Will not return VERR_INTERRUPTED.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param Thread The thread to wait for.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
fa9e4066f08beec538e775443c5be79dd423fcabahrens * an indefinite wait.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param prc Where to store the return code of the thread. Optional.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(int) RTThreadWait(RTTHREAD Thread, unsigned cMillies, int *prc)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = rtThreadWait(Thread, cMillies, prc, true);
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(rc != VERR_INTERRUPTED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadWait);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Wait for the thread to terminate, return on interruption.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param Thread The thread to wait for.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * an indefinite wait.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param prc Where to store the return code of the thread. Optional.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadWaitNoResume(RTTHREAD Thread, unsigned cMillies, int *prc)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rtThreadWait(Thread, cMillies, prc, false);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadWaitNoResume);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Changes the type of the specified thread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns iprt status code.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param Thread The thread which type should be changed.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param enmType The new thread type.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(int) RTThreadSetType(RTTHREAD Thread, RTTHREADTYPE enmType)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Validate input.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ( enmType > RTTHREADTYPE_INVALID
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw && enmType < RTTHREADTYPE_END)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(Thread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rtThreadIsAlive(pThread))
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Do the job.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_TMP(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_RW(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = rtThreadNativeSetPriority(pThread, enmType);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicXchgSize(&pThread->enmType, enmType);
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_THREAD_UNLOCK_RW(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_FAILURE(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Log(("RTThreadSetType: failed on thread %p (%s), rc=%Rrc!!!\n", Thread, pThread->szName, rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = VERR_THREAD_IS_DEAD;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = VERR_INVALID_HANDLE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens AssertMsgFailed(("enmType=%d\n", enmType));
fa9e4066f08beec538e775443c5be79dd423fcabahrens rc = VERR_INVALID_PARAMETER;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadSetType);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Gets the type of the specified thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns The thread type.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns RTTHREADTYPE_INVALID if the thread handle is invalid.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param Thread The thread in question.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensRTDECL(RTTHREADTYPE) RTThreadGetType(RTTHREAD Thread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTTHREADTYPE enmType = RTTHREADTYPE_INVALID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(Thread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw enmType = pThread->enmType;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return enmType;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadGetType);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#ifdef IN_RING3
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Recalculates scheduling attributes for the default process
fa9e4066f08beec538e775443c5be79dd423fcabahrens * priority using the specified priority type for the calling thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The scheduling attributes are targeted at threads and they are protected
fa9e4066f08beec538e775443c5be79dd423fcabahrens * by the thread read-write semaphore, that's why RTProc is forwarding the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * operation to RTThread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @remarks Will only work for strict builds.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint rtThreadDoCalcDefaultPriority(RTTHREADTYPE enmType)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_THREAD_LOCK_TMP(Tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_THREAD_LOCK_RW(Tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens int rc = rtSchedNativeCalcDefaultPriority(enmType);
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_THREAD_UNLOCK_RW(Tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Thread enumerator - sets the priority of one thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns 0 to continue.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns !0 to stop. In our case a VERR_ code.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pNode The thread node.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pvUser The new priority.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(int) rtThreadSetPriorityOne(PAVLPVNODECORE pNode, void *pvUser)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = (PRTTHREADINT)pNode;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!rtThreadIsAlive(pThread))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = rtThreadNativeSetPriority(pThread, pThread->enmType);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc)) /* hide any warnings */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return VINF_SUCCESS;
fa9e4066f08beec538e775443c5be79dd423fcabahrens return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Attempts to alter the priority of the current process.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The scheduling attributes are targeted at threads and they are protected
fa9e4066f08beec538e775443c5be79dd423fcabahrens * by the thread read-write semaphore, that's why RTProc is forwarding the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * operation to RTThread. This operation also involves updating all thread
fa9e4066f08beec538e775443c5be79dd423fcabahrens * which is much faster done from RTThread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns iprt status code.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param enmPriority The new priority.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint rtThreadDoSetProcPriority(RTPROCPRIORITY enmPriority)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlow(("rtThreadDoSetProcPriority: enmPriority=%d\n", enmPriority));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * First validate that we're allowed by the OS to use all the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * scheduling attributes defined by the specified process priority.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_TMP(Tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_THREAD_LOCK_RW(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = rtProcNativeSetPriority(enmPriority);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Update the priority of existing thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = RTAvlPVDoWithAll(&g_ThreadTree, true, rtThreadSetPriorityOne, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicXchgSize(&g_enmProcessPriority, enmPriority);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Failed, restore the priority.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtProcNativeSetPriority(g_enmProcessPriority);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTAvlPVDoWithAll(&g_ThreadTree, true, rtThreadSetPriorityOne, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_UNLOCK_RW(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlow(("rtThreadDoSetProcPriority: returns %Rrc\n", rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Change the thread state to blocking.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param hThread The current thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param enmState The sleep state.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param fReallySleeping Really going to sleep now.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, bool fReallySleeping)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(RTTHREAD_IS_SLEEPING(enmState));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = hThread;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread != NIL_RTTHREAD)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
fa9e4066f08beec538e775443c5be79dd423fcabahrens Assert(pThread == RTThreadSelf());
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (rtThreadGetState(pThread) == RTTHREADSTATE_RUNNING)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadSetState(pThread, enmState);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASMAtomicWriteBool(&pThread->fReallySleeping, fReallySleeping);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadBlocking);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Unblocks a thread.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function is paired with rtThreadBlocking.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param hThread The current thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param enmCurState The current state, used to check for nested blocking.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The new state will be running.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(void) RTThreadUnblocked(RTTHREAD hThread, RTTHREADSTATE enmCurState)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = hThread;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread != NIL_RTTHREAD)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert(pThread == RTThreadSelf());
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicWriteBool(&pThread->fReallySleeping, false);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTTHREADSTATE enmActualState = rtThreadGetState(pThread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (enmActualState == enmCurState)
fa9e4066f08beec538e775443c5be79dd423fcabahrens {
fa9e4066f08beec538e775443c5be79dd423fcabahrens rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ( pThread->LockValidator.pRec
fa9e4066f08beec538e775443c5be79dd423fcabahrens && pThread->LockValidator.enmRecState == enmCurState)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* This is a bit ugly... :-/ */
569e6c63191416b7413c148fd5a6194a0b820b2cmarks else if ( ( enmActualState == RTTHREADSTATE_TERMINATED
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw || enmActualState == RTTHREADSTATE_INITIALIZING)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw && pThread->LockValidator.pRec)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Assert( pThread->LockValidator.pRec == NULL
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw || RTTHREAD_IS_SLEEPING(enmActualState));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadUnblocked);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the current thread state.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns The thread state.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param hThread The thread.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(RTTHREADSTATE) RTThreadGetState(RTTHREAD hThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTTHREADSTATE enmState = RTTHREADSTATE_INVALID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(hThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
569e6c63191416b7413c148fd5a6194a0b820b2cmarks {
569e6c63191416b7413c148fd5a6194a0b820b2cmarks enmState = rtThreadGetState(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return enmState;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadGetState);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(RTTHREADSTATE) RTThreadGetReallySleeping(RTTHREAD hThread)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTTHREADSTATE enmState = RTTHREADSTATE_INVALID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PRTTHREADINT pThread = rtThreadGet(hThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pThread)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw enmState = rtThreadGetState(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!ASMAtomicUoReadBool(&pThread->fReallySleeping))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw enmState = RTTHREADSTATE_RUNNING;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rtThreadRelease(pThread);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return enmState;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRT_EXPORT_SYMBOL(RTThreadGetReallySleeping);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
fa9e4066f08beec538e775443c5be79dd423fcabahrens/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Translate a thread state into a string.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @returns Pointer to a read-only string containing the state name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param enmState The state.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwRTDECL(const char *) RTThreadStateName(RTTHREADSTATE enmState)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (enmState)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case RTTHREADSTATE_INVALID: return "INVALID";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_INITIALIZING: return "INITIALIZING";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_TERMINATED: return "TERMINATED";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_RUNNING: return "RUNNING";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_CRITSECT: return "CRITSECT";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_EVENT: return "EVENT";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_EVENT_MULTI: return "EVENT_MULTI";
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case RTTHREADSTATE_FAST_MUTEX: return "FAST_MUTEX";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_MUTEX: return "MUTEX";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_RW_READ: return "RW_READ";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_RW_WRITE: return "RW_WRITE";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_SLEEP: return "SLEEP";
fa9e4066f08beec538e775443c5be79dd423fcabahrens case RTTHREADSTATE_SPIN_MUTEX: return "SPIN_MUTEX";
fa9e4066f08beec538e775443c5be79dd423fcabahrens default: return "UnknownThreadState";
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensRT_EXPORT_SYMBOL(RTThreadStateName);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif /* IN_RING3 */
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef IPRT_WITH_GENERIC_TLS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Thread enumerator - clears a TLS entry.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @returns 0.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * @param pNode The thread node.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param pvUser The TLS index.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic DECLCALLBACK(int) rtThreadClearTlsEntryCallback(PAVLPVNODECORE pNode, void *pvUser)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens PRTTHREADINT pThread = (PRTTHREADINT)pNode;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RTTLS iTls = (RTTLS)(uintptr_t)pvUser;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASMAtomicWritePtr(&pThread->apvTlsEntries[iTls], NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Helper for the generic TLS implementation that clears a given TLS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * entry on all threads.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @param iTls The TLS entry. (valid)
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid rtThreadClearTlsEntry(RTTLS iTls)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_TMP(Tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw RT_THREAD_LOCK_RD(Tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens RTAvlPVDoWithAll(&g_ThreadTree, true /* fFromLeft*/, rtThreadClearTlsEntryCallback, (void *)(uintptr_t)iTls);
fa9e4066f08beec538e775443c5be79dd423fcabahrens RT_THREAD_UNLOCK_RD(Tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif /* IPRT_WITH_GENERIC_TLS */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
4c841f6070b4f88f9dc008de526b313bbebd4e32marks