⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rvthread.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
    else
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

    /* Set up thread pointer for those OS's that can do it from */
    /* outside the task itself. Its better to know  about a problem now. */
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) || (RV_THREAD_TYPE == RV_THREAD_PSOS) || \
    (RV_THREAD_TYPE == RV_THREAD_NUCLEUS) || (RV_THREAD_TYPE == RV_THREAD_OSE)
    if(result == RV_OK) {
        result = RvThreadSetupThreadPtr(th);
        if(result != RV_OK)
            RvThreadDelete(th); /* Undo the thread creation */
    }
#endif

    if(result == RV_OK)
        th->state = RV_THREAD_STATE_CREATED;

    if(RvLockRelease(&th->datalock) != RV_OK) {
        /* Deep trouble, do our best. */
        th->state = RV_THREAD_STATE_CREATED;
        RvThreadDelete(th); /* Undo the thread creation */
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
    }

    return result;
}

/* Do anything special required to set up a stack for the OS including */
/* allocating it if needed. The elements stackaddr, stackstart, and */
/* stackallocated should be dealt with as needed for the OS. Called */
/* internally only so locking is not needed (should be done by caller). */
static RvStatus RvThreadSetupStack(RvThread *th)
{
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) || (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    RvStatus result;
#endif

    /* For pSOS, OSE, and Win32 we really do nothing since we can't control */
    /* the stack. For POSIX (and variations), we could allocate the stack but */
    /* it causes problems on exit so we won't allow it. */

    /* For some OS's we must allocate the stack space if it hasn't been done for us */
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) || (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    if(th->stackaddr == NULL) {
        result = RvMemoryAlloc(NULL, &th->stackaddr, th->stacksize);
        if(result != RV_OK)
            return result;
        th->stackallocated = RV_TRUE;
    }
#endif

    /* Set stackstart to beginning of stack memory to use */
    th->stackstart = th->stackaddr;

    /* do any special manipulations to stack pointers */
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) && (_STACK_DIR == _STACK_GROWS_DOWN)
    /* Some architectures need stack pointer to be at end of memory block */
    th->stackstart += th->realstacksize;
#endif

    return RV_OK;
}

/* Actually start the thread. Obviously it must have already been created. */
RVCOREAPI RvStatus RVCALLCONV RvThreadStart(RvThread *th)
{
    RvStatus result;
#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
    unsigned long args[4]; /* For passing pSOS arguments */
    unsigned long errCode;
#endif

#if defined(RV_NULLCHECK)
    if(th == NULL)
        return RvThreadErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_THREAD_TYPE == RV_THREAD_NONE)
    result = RvThreadErrorCode(RV_ERROR_NOTSUPPORTED);
    return result;
#endif

    result = RV_OK;
    if(RvLockGet(&th->datalock) != RV_OK)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);

    /* We can't start something that hasn't been created or has already been started */
    if(th->state != RV_THREAD_STATE_CREATED){
        if(th->state == RV_THREAD_STATE_INIT) {
            result = RvThreadErrorCode(RV_THREAD_ERROR_NOTCREATED);
        } else result = RvThreadErrorCode(RV_THREAD_ERROR_RUNNING);
        RvLockRelease(&th->datalock);
        return result;
    }

    th->state = RV_THREAD_STATE_STARTING;

    /* Actually tell the OS to start running the task */
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS)
    if(taskActivate(th->id) != OK)
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
    args[0] = (unsigned long)th;
    args[1] = 0;
    args[2] = 0;
    args[3] = 0;
    errCode = t_start(th->id, th->attr.mode, RvThreadWrapper, args);
    if(errCode != 0)
    {
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
    }
#endif
#if (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    if(NU_Resume_Task(th->id) != NU_SUCCESS)
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_THREAD_TYPE == RV_THREAD_OSE)
    start(th->id); /* No error codes */
#endif
#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    if(pthread_create(&th->id, &th->tcb, RvThreadWrapper, th) != 0)
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
    if(ResumeThread(th->tcb) != 1)
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

    if(RvLockRelease(&th->datalock) != RV_OK)
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
    return result;
}

/* Attach thread pointer to the task so that it can be retrieved by */
/* the RvThreadCurrent function. If an OS can only attach to the */
/* current thread (instead of that pointer to by th) then it should */
/* do so but the caller needs to account for it. Called internally */
/* only so locking is not needed (should be done by caller).*/
static RvStatus RvThreadSetupThreadPtr(RvThread *th)
{
#if (RV_THREAD_TYPE == RV_THREAD_NONE)
    RvThreadCurrentPtr = th;
#endif

#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS)
        /* Use a task variable to store a copy of the thread pointer */
    if(taskVarAdd(th->id, (int *)&RvThreadCurrentPtr) != OK)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
    if(taskVarSet(th->id, &RvThreadCurrentPtr, (int)th) != OK)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
        /* Use a task variable to store a copy of the thread pointer */
#if (RV_OS_VERSION == RV_OS_PSOS_2_0)
    unsigned long errCode;

    errCode = t_setreg((unsigned long)th->id,
                       (unsigned long)0/*TASK_REGISTER_SLOT*/,
                       (unsigned long)th);
    if(errCode != 0)
    {
    }
#else
    if(t_addvar(th->id, (void **)&RvThreadCurrentPtr, (void *)th) != 0)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif
#endif

#if (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    /* Used the reseved element of the tcb structure to save a copy of the thread pointer */
    th->id->tc_app_reserved_1 = (UNSIGNED)th;
#endif

#if (RV_THREAD_TYPE == RV_THREAD_OSE)
    /* Use the environment to store a copy of the thread pointer */
    if(set_envp(th->id, RV_THREAD_ENVPTR, (OSADDRESS)th) == 0)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    /* Use a thread specific variable to store a copy of the thread pointer. */
    /* RvThreadCurrentKey must be set up in RvThreadInit. */
    /**** Pointer is set for current task NOT the task pointer to by th. ****/
    if(pthread_setspecific(RvThreadCurrentKey, (void *)th) != 0)
        return 0;
#endif

#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
    /* Use thread local storage to save a copy of the thread pointer. */
    /* RvThreadCurrentKey must be set up in RvThreadInit. */
    /**** Pointer is set for current task NOT the task pointer to by th. ****/
    if(TlsSetValue(RvThreadCurrentKey, (LPVOID)th) == 0)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

    return RV_OK;
}

/* Remove thread pointer from a task. Obviously, if the pointer */
/* can only be removed from the current task then that is what it */
/* will do. */
static RvStatus RvThreadRemoveThreadPtr(RvThread *th)
{
#if (RV_THREAD_TYPE == RV_THREAD_NONE)
    RvThreadCurrentPtr = NULL;
#endif

#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS)
    /* A task variable was used to store a copy of the thread pointer, clear and remove it. */
    if(taskVarSet(th->id, &RvThreadCurrentPtr, 0) != OK)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
    if(taskVarDelete(th->id, (int *)&RvThreadCurrentPtr) != OK)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
#if (RV_OS_VERSION == RV_OS_PSOS_2_0)
    /* A task variable was used to store a copy of the thread pointer, so we clear it
       but we cant actually remove it. */
    unsigned long errCode;

    errCode = t_setreg((unsigned long)th->id,
                       (unsigned long)TASK_REGISTER_SLOT,
                       (unsigned long)0);
    if(errCode != 0)
    {
    }
    else
        printf("RvThreadRemoveThreadPtr: t_setreg succeded. storing %d.\n", 0);

#else
    /* A task variable was used to store a copy of the thread pointer, remove it. */
    /* We can't clear it from another thread so don't worry about it. */
    if(t_delvar(th->id, (void **)&RvThreadCurrentPtr) != 0)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif
#endif

#if (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    /* Used the reseved element of the tcb structure, just clear it. */
    th->id->tc_app_reserved_1 = NULL;
#endif

#if (RV_THREAD_TYPE == RV_THREAD_OSE)
    /* Used an environment variable to store a copy of the thread pointer */
    if(set_env(th->id, RV_THREAD_ENVPTR, NULL) == 0) /* This should clear it. */
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    /* Used a thread specific variable to store a copy of the thread pointer, just clear it. */
    /**** Pointer is cleared for current task NOT the task pointer to by th. ****/
    if(pthread_setspecific(RvThreadCurrentKey, NULL) != 0)
        return 0;
#endif

#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
    RV_UNUSED_ARG(th);

    /* Used thread local storage to save a copy of the thread pointer, just clear it. */
    /**** Pointer is cleared for current task NOT the task pointer to by th. ****/
    if(TlsSetValue(RvThreadCurrentKey, NULL) == 0)
        return RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

    return RV_OK;
}

/* Can only be used by threads which have been created using this module */
/* or have used RvThreadConstructFromUserThread to attach to a user thread. */
RVCOREAPI RvThread * RVCALLCONV RvThreadCurrent(void)
{
    RvThread *result;

#if (RV_THREAD_TYPE == RV_THREAD_NONE)
    result = RvThreadCurrentPtr;
#endif

#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) || ((RV_THREAD_TYPE == RV_THREAD_PSOS) && (RV_TOOL_TYPE != RV_TOOL_TYPE_CADUL))
    RvThreadId id;
    id = RvThreadCurrentId(); /* We need to check for tasks which have no variable set */
    if(RvThreadCurrentPtr->id == id)
        result = RvThreadCurrentPtr;
    else
        result = NULL;
#endif
#if (RV_THREAD_TYPE == RV_THREAD_PSOS) && (RV_OS_VERSION == RV_OS_PSOS_2_0)
    RvThreadId id;
    unsigned long errCode;

    id = RvThreadCurrentId();
    errCode = t_getreg((unsigned long)id,
                       (unsigned long)TASK_REGISTER_SLOT,
                       (unsigned long*)RvThreadCurrentPtr);
    if(errCode != 0)
    {
    }

    if(RvThreadCurrentPtr->id == id)
        result = RvThreadCurrentPtr;
    else
        result = NULL;
#endif
#if (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    /* IMPORTANT: User create threads must make sure tc_app_reserved_1 is set to 0 */
    /* for any thread making calls to this function but haven't been constructed */
    /* with either construct function in the module. */
    TC_TCB *task; /* TC_TCB = NU_TASK but only defined that way when compiling in DEBUG */
    task = (TC_TCB *)NU_Current_Task_Pointer();
    result = (RvThread *)task->tc_app_reserved_1;
#endif
#if (RV_THREAD_TYPE == RV_THREAD_OSE)
    result = (RvThread *)get_envp(0, RV_THREAD_ENVPTR);
#endif
#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    result = (RvThread *)pthread_getspecific(RvThreadCurrentKey);
#endif
#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
    result = (RvThread *)TlsGetValue(RvThreadCurrentKey);
#endif

    return result;
}

/* Returns the OS specific thread id */
RVCOREAPI RvThreadId RVCALLCONV RvThreadCurrentId(void)
{
#if (RV_THREAD_TYPE == RV_THREAD_NONE)
    return 1;
#endif
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS)
    return taskIdSelf();
#endif
#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
    RvThreadId current;
    t_ident(0, 0, &current);
    return current;
#endif
#if (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    return NU_Current_Task_Pointer();
#endif
#if (RV_THREAD_TYPE == RV_THREAD_OSE)
    return current_process();
#endif
#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    return pthread_self();
#endif
#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
    return GetCurrentThreadId();
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -