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

📄 rvthread.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
/***********************************************************************
Filename   : rvthread.c
Description: thread management functions
************************************************************************
      Copyright (c) 2001,2002 RADVISION Inc. and RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Inc. and RADVISION Ltd.. No part of this document may be
reproduced in any form whatsoever without written prior approval by
RADVISION Inc. or RADVISION Ltd..

RADVISION Inc. and RADVISION Ltd. reserve the right to revise this
publication and make changes without obligation to notify any person of
such revisions or changes.
***********************************************************************/
#include "rvthread.h"
#include "rvmemory.h"
#include "rvstdio.h"
#include <string.h>

#if (RV_THREAD_TYPE == RV_THREAD_NONE)
static RvThread *RvThreadCurrentPtr; /* Used to track current thread ptr */
#define RV_THREAD_WRAPPER_STACK 0
#define RV_THREAD_PRIORITY_MIN 0
#define RV_THREAD_PRIORITY_MAX 0
#define RV_THREAD_DOSLEEP tm_wkafter
#endif

#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS)
#include <private/taskLibP.h>
static RvThread *RvThreadCurrentPtr; /* Used to track current thread ptr */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <phile.h>
#include <pna.h>
#include <psoscfg.h>
extern pSOS_CT PsosCfg; /* for looking up clock rate */
static RvThread *RvThreadCurrentPtr; /* Used to track current thread ptr */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
#include <target.h>
#include <tc_defs.h>
#endif

#if (RV_THREAD_TYPE == RV_THREAD_OSE)
#define RV_THREAD_ENVPTR "rvthread_ptr" /* name of variable to hold RvThread pointer */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
#include <errno.h>
static pthread_key_t RvThreadCurrentKey; /* Used to track current thread ptr */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_WINCE)
#include <windows.h>
static DWORD RvThreadCurrentKey; /* Used to track current thread ptr */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_WIN32)
#include <process.h>
static DWORD RvThreadCurrentKey; /* Used to track current thread ptr */
#endif

/* define the default attributes since they may be a structure */
static RvThreadAttr RvDefaultThreadAttr = RV_THREAD_ATTRIBUTE_DEFAULT;

/* thread states */
#define RV_THREAD_STATE_INIT      RvInt32Const(0)
#define RV_THREAD_STATE_CREATED   RvInt32Const(1)
#define RV_THREAD_STATE_STARTING  RvInt32Const(2)
#define RV_THREAD_STATE_RUNNING   RvInt32Const(3)
#define RV_THREAD_STATE_EXITING   RvInt32Const(4)
#define RV_THREAD_STATE_DESTROYED RvInt32Const(5)
#define RV_THREAD_STATE_SPECIAL   RvInt32Const(6) /* Dummy thread attached to application controlled task */

/* indicate any additional stack space that is needed for our own use */
/* but is not used by the OS for the actual stack */
#define RV_THREAD_ADDITIONAL_STACK 0

#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS)&& (_STACK_DIR == _STACK_GROWS_DOWN)
/* Add some padding if the stack grows down just in case the stack */
/* operations don't predecrement. */
#undef RV_THREAD_ADDITIONAL_STACK
#define RV_THREAD_ADDITIONAL_STACK _STACK_ALIGN_SIZE
#endif

/* Thread specific variable info */
typedef struct {
    RvBool active;             /* set to RV_TRUE when variable is in use */
    RvThreadVarFunc exitfunc;  /* Function to call upon a thread exit */
    RvChar name[RV_THREAD_MAX_VARNAMESIZE]; /* Name of variable. */
} RvThreadVar;

static RvLock RvThreadLock; /* RvThreadVars lock to prevent bizare construct/destruct sequences */
static RvThreadVar RvThreadVars[RV_THREAD_MAX_VARS]; /* Thread specific variable info */

static RvStatus RvThreadDelete(RvThread *th);
static RvStatus RvThreadWaitOnExit(RvThread *th);
static RvStatus RvThreadSetupStack(RvThread *th);
static RvStatus RvThreadCallExits(RvThread *th);
static RvStatus RvThreadGetOsPriority(RvThreadId id, RvInt32 *priority);
static RvStatus RvThreadSetupThreadPtr(RvThread *th);
static RvStatus RvThreadRemoveThreadPtr(RvThread *th);

#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || \
    (RV_THREAD_TYPE == RV_THREAD_WINCE) || \
    (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_POSIX) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
static void RvThreadExitted(IN void* ptr);
#endif

/* Lets make error codes a little easier to type */
#define RvThreadErrorCode(_e) RvErrorCode(RV_ERROR_LIBCODE_CCORE, RV_CCORE_MODULE_THREAD, (_e))

/* Must be called only once and before any other calls to rvthread. */
RvStatus RvThreadInit(void)
{
    RvStatus result;
    RvUint32 i;

    result = RvLockConstruct(&RvThreadLock);
    if(result != RV_OK)
        return result;
    for(i = 0; i < RV_THREAD_MAX_VARS; i++) {
        RvThreadVars[i].active = RV_FALSE;
        RvThreadVars[i].name[0] = '\0';
    }

    /* OS specific setup */
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) || (RV_THREAD_TYPE == RV_THREAD_PSOS) || \
    (RV_THREAD_TYPE == RV_THREAD_NONE)
    RvThreadCurrentPtr = NULL; /* Make sure we're not getting a random value */
#endif
#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    /* create a thread specific variable for holding copies of thread pointers */
    if(pthread_key_create(&RvThreadCurrentKey, RvThreadExitted) != 0)
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
    /* create a tls variable for holding copies of thread pointers */
    RvThreadCurrentKey = TlsAlloc();
    if(RvThreadCurrentKey < 0)
        result = RvThreadErrorCode(RV_ERROR_UNKNOWN);
#endif

    if(result != RV_OK)
        RvLockDestruct(&RvThreadLock);
    return result;
}

/* Must be called only once and after all threads have been destructed. */
RvStatus RvThreadEnd(void)
{
    RvLockDestruct(&RvThreadLock);

    /* OS specific cleanup */
#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    pthread_key_delete(RvThreadCurrentKey);
#endif
#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
    TlsFree(RvThreadCurrentKey); /* need to delete tls variable */
#endif

    return RV_OK;
}



#if (RV_THREAD_TYPE != RV_THREAD_NONE)

/* Each thread wrapper declaration is different. Each should declare the proper */
/* definition and make sure the variable th is set. Also make sure that the */
/* return value is valid. For each OS, also define RV_THREAD_WRAPPER_STACK to */
/* indicate how much additional stack the wrapper needs. */
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS)
#define RV_THREAD_WRAPPER_STACK 64
static int RvThreadWrapper(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10)
#endif

#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
#define RV_THREAD_WRAPPER_STACK 48
static void RvThreadWrapper(int arg1, int arg2, int arg3, int arg4)
#endif

#if (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
#define RV_THREAD_WRAPPER_STACK 48
static void RvThreadWrapper(UNSIGNED argc, void *arg1)
#endif

#if (RV_THREAD_TYPE == RV_THREAD_OSE)
#define RV_THREAD_WRAPPER_STACK 48
OS_PROCESS(RvThreadWrapper)
#endif

#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
#define RV_THREAD_WRAPPER_STACK (64 + PTHREAD_STACK_MIN)
static void* RvThreadWrapper(void* arg1)
#endif


#if (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE)
#define RV_THREAD_WRAPPER_STACK 64
static unsigned __stdcall RvThreadWrapper(void* arg1)
#endif

/* Body of Thread Wrapper */
{
    RvThread *th;

    /* OS specific setups */
#if (RV_THREAD_TYPE == RV_THREAD_OSE)
    /* Since OSE can't pass parameters, we just have to retrieve it. */
    RvThread *arg1;
    arg1 = RvThreadCurrent();
    if(arg1 == NULL)
        return;
#endif

    /* At this point arg1 should be the current thread ptr. */
    th = (RvThread *)arg1;

    /* We have to save the copy of the thread pointer here on some */
    /* OS's since we can't do it from outside the thread. */
#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_WIN32) || (RV_THREAD_TYPE == RV_THREAD_WINCE) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    if(RvThreadSetupThreadPtr(th) != RV_OK) {
        /* We need to abort the best we can. */
        RvLockGet(&th->datalock);
        th->state = RV_THREAD_STATE_EXITING;
        RvLockRelease(&th->datalock);
        RvSemaphorePost(&th->exitsignal);
#if (RV_THREAD_TYPE == RV_THREAD_WINCE)
        ExitThread(0); /* does not return */
#endif
#if (RV_THREAD_TYPE == RV_THREAD_WIN32)
        _endthreadex(0); /* does not return */
#endif
#if (RV_THREAD_TYPE == RV_THREAD_POSIX) || (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || \
    (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
        return 0;
#endif
    }
#endif /* Save thread ptr */

    RvLockGet(&th->datalock);
    th->state = RV_THREAD_STATE_RUNNING;
    RvLockRelease(&th->datalock);

    th->func(th, th->data);

    RvLockGet(&th->datalock);
    th->state = RV_THREAD_STATE_EXITING;
    RvLockRelease(&th->datalock);

    RvLockGet(&RvThreadLock); /* Prevent add/remove race conditions */
    RvThreadCallExits(th); /* Do thread specific variable cleanup */
    RvLockRelease(&RvThreadLock);

    RvThreadRemoveThreadPtr(th); /* Remove our thread pointer. */

    RvSemaphorePost(&th->exitsignal);

#if (RV_THREAD_TYPE == RV_THREAD_OSE)
    kill_proc(th->id); /* Only way to cause clean-up */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_PSOS)
    /* This sequence must be followed or pSOS will not clean everything up */
    fclose(0);
    close_f(0);
    close((int)0);
    free((void *)-1);
    t_delete(0); /* does not return */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_WINCE)
    ExitThread(0); /* does not return */
#endif
#if (RV_THREAD_TYPE == RV_THREAD_WIN32)
    _endthreadex(0); /* does not return */
#endif

#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) || (RV_THREAD_TYPE == RV_THREAD_POSIX) || \
    (RV_THREAD_TYPE == RV_THREAD_SOLARIS) || (RV_THREAD_TYPE == RV_THREAD_WIN32) || \
    (RV_THREAD_TYPE == RV_THREAD_WINCE) || (RV_THREAD_TYPE == RV_THREAD_UNIXWARE)
    return 0;
#endif
}

#endif /* (RV_THREAD_TYPE != RV_THREAD_NONE) */



/* Base thread construction. Set everything else to defaults */
RVCOREAPI RvStatus RVCALLCONV RvThreadConstruct(RvThread *th, RvThreadFunc func, void *data)
{
    RvStatus result;
    RvUint32 i;

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


    RvLockGet(&RvThreadLock);

    result = RvLockConstruct(&th->datalock);
    if(result != RV_OK) {
        RvLockRelease(&RvThreadLock);
        return result;
    }
    result = RvSemaphoreConstruct(&th->exitsignal, RvUint32Const(0));
    if(result != RV_OK) {
        RvLockDestruct(&th->datalock);
        RvLockRelease(&RvThreadLock);
        return result;
    }

    th->state = RV_THREAD_STATE_INIT;
    th->stackstart = NULL;
    th->stackallocated = RV_FALSE;
    th->autodelete = RV_FALSE;

    /* Use RvThreadSetStack to initialize stack info since that has */
    /* the logic for dealing with all the special cases. */
    result = RvThreadSetStack(th, NULL, RV_THREAD_STACKSIZE_DEFAULT);
    if(result != RV_OK) {
        RvLockDestruct(&th->datalock);
        RvLockRelease(&RvThreadLock);
        return result;
    }

    strncpy(th->name, "RvDefault", RV_THREAD_MAX_NAMESIZE);
    th->waitdestruct = RV_FALSE;
    th->func = func;
    th->data = data;
    th->priority = RV_THREAD_PRIORITY_DEFAULT;
    memcpy(&th->attr, &RvDefaultThreadAttr, sizeof(th->attr));
    for(i = 0; i < RV_THREAD_MAX_VARS; i++)
        th->vars[i] = NULL; /* Start with vars cleared */

    /* OS specific initializations */
#if (RV_THREAD_TYPE == RV_THREAD_VXWORKS) || (RV_THREAD_TYPE == RV_THREAD_NUCLEUS)
    th->id = (RvThreadId)&th->tcb; /* id is just a pointer to the tcb which we control */
#endif

⌨️ 快捷键说明

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