Esempio n. 1
0
/**
 * Signal the user event.
 *
 * @returns     iprt status code.
 */
RTDECL(int) RTThreadUserSignal(RTTHREAD Thread)
{
    int             rc;
    PRTTHREADINT    pThread = rtThreadGet(Thread);
    if (pThread)
    {
        rc = RTSemEventMultiSignal(pThread->EventUser);
        rtThreadRelease(pThread);
    }
    else
        rc = VERR_INVALID_HANDLE;
    return rc;
}
Esempio n. 2
0
RTDECL(RTTHREADSTATE) RTThreadGetReallySleeping(RTTHREAD hThread)
{
    RTTHREADSTATE   enmState = RTTHREADSTATE_INVALID;
    PRTTHREADINT    pThread  = rtThreadGet(hThread);
    if (pThread)
    {
        enmState = rtThreadGetState(pThread);
        if (!ASMAtomicUoReadBool(&pThread->fReallySleeping))
            enmState = RTTHREADSTATE_RUNNING;
        rtThreadRelease(pThread);
    }
    return enmState;
}
Esempio n. 3
0
/**
 * Wait for the user event, return on interruption.
 *
 * @returns     iprt status code.
 * @param       Thread          The thread to wait for.
 * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
 *                              an indefinite wait.
 */
RTDECL(int) RTThreadUserWaitNoResume(RTTHREAD Thread, RTMSINTERVAL cMillies)
{
    int             rc;
    PRTTHREADINT    pThread = rtThreadGet(Thread);
    if (pThread)
    {
        rc = RTSemEventMultiWaitNoResume(pThread->EventUser, cMillies);
        rtThreadRelease(pThread);
    }
    else
        rc = VERR_INVALID_HANDLE;
    return rc;
}
RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue)
{
    if (RT_UNLIKELY(    iTls < 0
                    ||  iTls >= RTTHREAD_TLS_ENTRIES
                    ||  !ASMBitTest(&g_au32AllocatedBitmap[0], iTls)))
        return VERR_INVALID_PARAMETER;

    PRTTHREADINT pThread = rtThreadGet(RTThreadSelf());
    AssertReturn(pThread, VERR_NOT_SUPPORTED);
    pThread->apvTlsEntries[iTls] = pvValue;
    rtThreadRelease(pThread);
    return VINF_SUCCESS;
}
Esempio n. 5
0
/**
 * Wait for the thread to terminate.
 *
 * @returns     iprt status code.
 * @param       Thread          The thread to wait for.
 * @param       cMillies        The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for
 *                              an indefinite wait.
 * @param       prc             Where to store the return code of the thread. Optional.
 * @param       fAutoResume     Whether or not to resume the wait on VERR_INTERRUPTED.
 */
static int rtThreadWait(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc, bool fAutoResume)
{
    int rc = VERR_INVALID_HANDLE;
    if (Thread != NIL_RTTHREAD)
    {
        PRTTHREADINT pThread = rtThreadGet(Thread);
        if (pThread)
        {
            if (pThread->fFlags & RTTHREADFLAGS_WAITABLE)
            {
                if (fAutoResume)
                    rc = RTSemEventMultiWait(pThread->EventTerminated, cMillies);
                else
                    rc = RTSemEventMultiWaitNoResume(pThread->EventTerminated, cMillies);
                if (RT_SUCCESS(rc))
                {
                    if (prc)
                        *prc = pThread->rc;

                    /*
                     * If the thread is marked as waitable, we'll do one additional
                     * release in order to free up the thread structure (see how we
                     * init cRef in rtThreadAlloc()).
                     */
                    if (ASMAtomicBitTestAndClear(&pThread->fFlags, RTTHREADFLAGS_WAITABLE_BIT))
                        rtThreadRelease(pThread);
                }
            }
            else
            {
                rc = VERR_THREAD_NOT_WAITABLE;
                AssertRC(rc);
            }
            rtThreadRelease(pThread);
        }
    }
    return rc;
}
Esempio n. 6
0
/**
 * Gets the name of a thread.
 *
 * @returns Pointer to readonly name string.
 * @returns NULL on failure.
 * @param   Thread      Thread handle of the thread to query the name of.
 */
RTDECL(const char *) RTThreadGetName(RTTHREAD Thread)
{
    PRTTHREADINT pThread;
    if (Thread == NIL_RTTHREAD)
        return NULL;
    pThread = rtThreadGet(Thread);
    if (pThread)
    {
        const char *szName = pThread->szName;
        rtThreadRelease(pThread);
        return szName;
    }
    return NULL;
}
Esempio n. 7
0
/**
 * Gets the name of the current thread thread.
 *
 * @returns Pointer to readonly name string.
 * @returns NULL on failure.
 */
RTDECL(const char *) RTThreadSelfName(void)
{
    RTTHREAD Thread = RTThreadSelf();
    if (Thread != NIL_RTTHREAD)
    {
        PRTTHREADINT pThread = rtThreadGet(Thread);
        if (pThread)
        {
            const char *szName = pThread->szName;
            rtThreadRelease(pThread);
            return szName;
        }
    }
    return NULL;
}
Esempio n. 8
0
RTDECL(int) RTThreadPoke(RTTHREAD hThread)
{
    AssertReturn(hThread != RTThreadSelf(), VERR_INVALID_PARAMETER);
    PRTTHREADINT pThread = rtThreadGet(hThread);
    AssertReturn(pThread, VERR_INVALID_HANDLE);

    int rc;
    if (g_iSigPokeThread != -1)
    {
        rc = pthread_kill((pthread_t)(uintptr_t)pThread->Core.Key, g_iSigPokeThread);
        rc = RTErrConvertFromErrno(rc);
    }
    else
        rc = VERR_NOT_SUPPORTED;

    rtThreadRelease(pThread);
    return rc;
}
Esempio n. 9
0
/**
 * Changes the type of the specified thread.
 *
 * @returns iprt status code.
 * @param   Thread      The thread which type should be changed.
 * @param   enmType     The new thread type.
 */
RTDECL(int) RTThreadSetType(RTTHREAD Thread, RTTHREADTYPE enmType)
{
    /*
     * Validate input.
     */
    int     rc;
    if (    enmType > RTTHREADTYPE_INVALID
        &&  enmType < RTTHREADTYPE_END)
    {
        PRTTHREADINT pThread = rtThreadGet(Thread);
        if (pThread)
        {
            if (rtThreadIsAlive(pThread))
            {
                /*
                 * Do the job.
                 */
                RT_THREAD_LOCK_RW();
                rc = rtThreadNativeSetPriority(pThread, enmType);
                if (RT_SUCCESS(rc))
                    ASMAtomicXchgSize(&pThread->enmType, enmType);
                RT_THREAD_UNLOCK_RW();
                if (RT_FAILURE(rc))
                    Log(("RTThreadSetType: failed on thread %p (%s), rc=%Rrc!!!\n", Thread, pThread->szName, rc));
            }
            else
                rc = VERR_THREAD_IS_DEAD;
            rtThreadRelease(pThread);
        }
        else
            rc = VERR_INVALID_HANDLE;
    }
    else
    {
        AssertMsgFailed(("enmType=%d\n", enmType));
        rc = VERR_INVALID_PARAMETER;
    }
    return rc;
}
Esempio n. 10
0
/**
 * Sets the name of a thread.
 *
 * @returns iprt status code.
 * @param   Thread      Thread handle of the thread to query the name of.
 * @param   pszName     The thread name.
 */
RTDECL(int) RTThreadSetName(RTTHREAD Thread, const char *pszName)
{
    /*
     * Validate input.
     */
    PRTTHREADINT pThread;
    size_t cchName = strlen(pszName);
    if (cchName >= RTTHREAD_NAME_LEN)
    {
        AssertMsgFailed(("pszName=%s is too long, max is %d\n", pszName, RTTHREAD_NAME_LEN - 1));
        return VERR_INVALID_PARAMETER;
    }
    pThread = rtThreadGet(Thread);
    if (!pThread)
        return VERR_INVALID_HANDLE;

    /*
     * Update the name.
     */
    pThread->szName[cchName] = '\0';    /* paranoia */
    memcpy(pThread->szName, pszName, cchName);
    rtThreadRelease(pThread);
    return VINF_SUCCESS;
}
Esempio n. 11
0
/**
 * Create a new thread.
 *
 * @returns iprt status code.
 * @param   pThread     Where to store the thread handle to the new thread. (optional)
 * @param   pfnThread   The thread function.
 * @param   pvUser      User argument.
 * @param   cbStack     The size of the stack for the new thread.
 *                      Use 0 for the default stack size.
 * @param   enmType     The thread type. Used for deciding scheduling attributes
 *                      of the thread.
 * @param   fFlags      Flags of the RTTHREADFLAGS type (ORed together).
 * @param   pszName     Thread name.
 */
RTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack,
                           RTTHREADTYPE enmType, unsigned fFlags, const char *pszName)
{
    int             rc;
    PRTTHREADINT    pThreadInt;

    LogFlow(("RTThreadCreate: pThread=%p pfnThread=%p pvUser=%p cbStack=%#x enmType=%d fFlags=%#x pszName=%p:{%s}\n",
             pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszName, pszName));

    /*
     * Validate input.
     */
    if (!VALID_PTR(pThread) && pThread)
    {
        Assert(VALID_PTR(pThread));
        return VERR_INVALID_PARAMETER;
    }
    if (!VALID_PTR(pfnThread))
    {
        Assert(VALID_PTR(pfnThread));
        return VERR_INVALID_PARAMETER;
    }
    if (!pszName || !*pszName || strlen(pszName) >= RTTHREAD_NAME_LEN)
    {
        AssertMsgFailed(("pszName=%s (max len is %d because of logging)\n", pszName, RTTHREAD_NAME_LEN - 1));
        return VERR_INVALID_PARAMETER;
    }
    if (fFlags & ~RTTHREADFLAGS_MASK)
    {
        AssertMsgFailed(("fFlags=%#x\n", fFlags));
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Allocate thread argument.
     */
    pThreadInt = rtThreadAlloc(enmType, fFlags, 0, pszName);
    if (pThreadInt)
    {
        RTNATIVETHREAD NativeThread;

        pThreadInt->pfnThread = pfnThread;
        pThreadInt->pvUser    = pvUser;
        pThreadInt->cbStack   = cbStack;

        rc = rtThreadNativeCreate(pThreadInt, &NativeThread);
        if (RT_SUCCESS(rc))
        {
            rtThreadInsert(pThreadInt, NativeThread);
            rtThreadRelease(pThreadInt);
            Log(("RTThreadCreate: Created thread %p (%p) %s\n", pThreadInt, NativeThread, pszName));
            if (pThread)
                *pThread = pThreadInt;
            return VINF_SUCCESS;
        }

        pThreadInt->cRefs = 1;
        rtThreadRelease(pThreadInt);
    }
    else
        rc = VERR_NO_TMP_MEMORY;
    LogFlow(("RTThreadCreate: Failed to create thread, rc=%Rrc\n", rc));
    AssertReleaseRC(rc);
    return rc;
}
RTDECL(RTTHREADNATIVESTATE) RTThreadGetNativeState(RTTHREAD hThread)
{
    RTTHREADNATIVESTATE enmRet  = RTTHREADNATIVESTATE_INVALID;
    PRTTHREADINT        pThread = rtThreadGet(hThread);
    if (pThread)
    {
        enmRet = RTTHREADNATIVESTATE_UNKNOWN;

        char szName[512];
        RTStrPrintf(szName, sizeof(szName), "/proc/self/task/%u/stat", pThread->tid);
        int fd = open(szName, O_RDONLY, 0);
        if (fd >= 0)
        {
            ssize_t cch = read(fd, szName, sizeof(szName) - 1);
            close(fd);
            if (cch > 0)
            {
                szName[cch] = '\0';

                /* skip the pid, the (comm name) and stop at the status char. */
                const char *psz = szName;
                while (   *psz
                       && (   *psz != ')'
                           || !RT_C_IS_SPACE(psz[1])
                           || !RT_C_IS_ALPHA(psz[2])
                           || !RT_C_IS_SPACE(psz[3])
                          )
                      )
                    psz++;
                if (*psz == ')')
                {
                    switch (psz[2])
                    {
                        case 'R':   /* running */
                            enmRet = RTTHREADNATIVESTATE_RUNNING;
                            break;

                        case 'S':   /* sleeping */
                        case 'D':   /* disk sleeping */
                            enmRet = RTTHREADNATIVESTATE_BLOCKED;
                            break;

                        case 'T':   /* stopped or tracking stop */
                            enmRet = RTTHREADNATIVESTATE_SUSPENDED;
                            break;

                        case 'Z':   /* zombie */
                        case 'X':   /* dead */
                            enmRet = RTTHREADNATIVESTATE_TERMINATED;
                            break;

                        default:
                            AssertMsgFailed(("state=%c\n", psz[2]));
                            enmRet = RTTHREADNATIVESTATE_UNKNOWN;
                            break;
                    }
                }
                else
                    AssertMsgFailed(("stat='%s'\n", szName));
            }
        }
        rtThreadRelease(pThread);
    }
    return enmRet;
}