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

📄 rvlock.c

📁 基于h323协议的软phone
💻 C
字号:
/***********************************************************************
Filename   : rvlock.c
Description: lock functions (actually a non-recursive mutex for locking)
************************************************************************
        Copyright (c) 2001 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 "rvlock.h"
#include "rvstdio.h"
#include <string.h>

#if (RV_LOCK_TYPE == RV_LOCK_SOLARIS)
#include <errno.h>

/* See if we have a Solaris that can set a mutex's protocol or not */
static RvBool RvLockTrySettingProtocol = RV_TRUE;
#endif

/* NOTE: all lock functions are only callable at task level */

/* define the default attributes since they may be a structure */
static RvLockAttr RvDefaultLockAttr = RV_LOCK_ATTRIBUTE_DEFAULT;

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

RvStatus RvLockInit(void)
{
    return RV_OK;
}

RvStatus RvLockEnd(void)
{
    return RV_OK;
}

#if (RV_LOCK_TYPE != RV_LOCK_NONE)
/* Don't include any other code if type is none */

RVCOREAPI
RvStatus RVCALLCONV RvLockConstruct(RvLock *lock)
{
#if (RV_LOCK_TYPE == RV_LOCK_SOLARIS)
    pthread_mutexattr_t ma;
    int result;
#endif
#if (RV_LOCK_TYPE == RV_LOCK_LINUX)
    pthread_mutexattr_t ma;
#endif
#if (RV_LOCK_TYPE == RV_LOCK_MANUAL)
    RvStatus result;
#endif

#if defined(RV_NULLCHECK)
    if(lock == NULL)
        return RvLockErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_LOCK_TYPE == RV_LOCK_SOLARIS) || (RV_LOCK_TYPE == RV_LOCK_LINUX)
    if(pthread_mutexattr_init(&ma) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#if (RV_LOCK_TYPE == RV_LOCK_SOLARIS)
    /* Should allow these along with _setprioceiling and */
    /* _setrobust_np to be set from config file. */
    if (RvLockTrySettingProtocol)
    {
        result = pthread_mutexattr_setprotocol(&ma, RvDefaultLockAttr.protocol);
        if(result != 0)
        {
            if (result == ENOSYS)
                RvLockTrySettingProtocol = RV_FALSE; /* Not supported - don't try anymore */
            else
                return RvLockErrorCode(RV_ERROR_UNKNOWN);
        }
    }
    if(pthread_mutexattr_setpshared(&ma, RvDefaultLockAttr.pshared) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
    if(pthread_mutexattr_settype(&ma, RvDefaultLockAttr.kind) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_LINUX)
    /* Linux only support one attribute */
    if(pthread_mutexattr_setkind_np(&ma, RvDefaultLockAttr.kind) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
    if(pthread_mutex_init(lock, &ma) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
    if(pthread_mutexattr_destroy(&ma) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif /* Solaris & Linux */

#if (RV_LOCK_TYPE == RV_LOCK_VXWORKS)
    *lock = semBCreate(RvDefaultLockAttr, SEM_FULL);
    if(*lock == NULL)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif

#if (RV_LOCK_TYPE == RV_LOCK_PSOS)
    if(mu_create("rv", RvDefaultLockAttr | MU_NORECURSIVE, 0, lock) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif

#if (RV_LOCK_TYPE == RV_LOCK_WIN32_MUTEX)
    *lock = CreateMutex(NULL, FALSE, NULL);
    if(*lock == NULL)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif

#if (RV_LOCK_TYPE == RV_LOCK_WIN32_CRITICAL)
#if (_WIN32_WINNT >= 0x0500)
    if(InitializeCriticalSectionAndSpinCount(lock, RvDefaultLockAttr) != 0) /* tune spincount for MP systems */
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#else
    InitializeCriticalSection(lock);
#endif
#endif

#if (RV_LOCK_TYPE == RV_LOCK_MANUAL)
    result = RvSemaphoreConstruct(lock, RvUint32Const(1));
    if(result != RV_OK)
        return result;
#endif

    return RV_OK;
}

RVCOREAPI
RvStatus RVCALLCONV RvLockDestruct(RvLock *lock)
{
#if (RV_LOCK_TYPE == RV_LOCK_MANUAL)
    RvStatus result;
#endif

#if defined(RV_NULLCHECK)
    if(lock == NULL)
        return RvLockErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_LOCK_TYPE == RV_LOCK_SOLARIS) || (RV_LOCK_TYPE == RV_LOCK_LINUX)
    if(pthread_mutex_destroy(lock) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_VXWORKS)
    if(semDelete(*lock) != OK)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_PSOS)
    if(mu_delete(*lock) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_WIN32_MUTEX)
    if(CloseHandle(*lock) == 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_WIN32_CRITICAL)
    DeleteCriticalSection(lock);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_MANUAL)
    result = RvSemaphoreDestruct(lock);
    if(result != RV_OK)
        return result;
#endif
    return RV_OK;
}

/* Block until lock is aquired */
RVCOREAPI
RvStatus RVCALLCONV RvLockGet(RvLock *lock)
{
#if defined(RV_NULLCHECK)
    if(lock == NULL)
        return RvLockErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_LOCK_TYPE == RV_LOCK_SOLARIS) || (RV_LOCK_TYPE == RV_LOCK_LINUX)
    if(pthread_mutex_lock(lock) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_VXWORKS)
    if(semTake(*lock, WAIT_FOREVER) != OK)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_PSOS)
    if(mu_lock(*lock, MU_WAIT, 0) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_WIN32_MUTEX)
    if(WaitForSingleObject(*lock, INFINITE) != WAIT_OBJECT_0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_WIN32_CRITICAL)
    EnterCriticalSection(lock);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_MANUAL)
    RvSemaphoreWait(lock);
#endif
    return RV_OK;
}

RVCOREAPI
RvStatus RVCALLCONV RvLockRelease(RvLock *lock)
{
#if defined(RV_NULLCHECK)
    if(lock == NULL)
        return RvLockErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_LOCK_TYPE == RV_LOCK_SOLARIS) || (RV_LOCK_TYPE == RV_LOCK_LINUX)
    if(pthread_mutex_unlock(lock) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_VXWORKS)
    if(semGive(*lock) != OK)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_PSOS)
    if(mu_unlock(*lock) != 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_WIN32_MUTEX)
    if(ReleaseMutex(*lock) == 0)
        return RvLockErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_WIN32_CRITICAL)
    LeaveCriticalSection(lock);
#endif
#if (RV_LOCK_TYPE == RV_LOCK_MANUAL)
    RvSemaphorePost(lock);
#endif
    return RV_OK;
}

RvStatus RvLockSetAttr(RvLockAttr *attr)
{
    if(attr != NULL) {
        memcpy(&RvDefaultLockAttr, attr, sizeof(RvDefaultLockAttr));
    }
    return RV_OK;
}

#endif /* NONE */

#if defined(RV_TEST_CODE)
#include "rvstdio.h"
#include "rvthread.h"
#include "rvmemory.h"

#define RvLockPrintError(_r) RvPrintf("Error %d/%d/%d\n",  RvErrorGetLib((_r)), RvErrorGetModule((_r)), RvErrorGetCode((_r)))

void RvLockTestThread(RvThread *th, void *data)
{
    RvLock *lock;
    RvStatus result;

    lock = (RvLock *)data;

    RvPrintf("Thread %p started.\n", th);

    RvPrintf("Thread: Trying to lock...\n");
    result = RvLockGet(lock);
    if(result != RV_OK) {
        RvPrintf("Thread Lock ");
        RvLockPrintError(result);
    } else RvPrintf("Thread RvLockGet OK\n");

    RvPrintf("Thread: Waiting for 10 seconds.\n");
    RvThreadNanosleep(RvInt64Const(10000000000));

    RvPrintf("Thread: RvLockRelease: ");
    result = RvLockRelease(lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvPrintf("Thread exiting.\n");
}

/* This test used rvthread, which uses rvlock, but its the */
/* best we can do, so test appropriately. */
void RvLockTest(void)
{
    RvStatus result;
    RvLock lock;
    RvThread th;

    /* Initialize modules we may need. */
    RvSemaphoreInit();

    RvPrintf("RvLockInit: ");
    result = RvLockInit();
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    /* Initialize other modules needed for the test that may need us*/
    RvMemoryInit();
    RvThreadInit();

    RvPrintf("RvLockConstruct: ");
    result = RvLockConstruct(&lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvPrintf("RvLockGet: ");
    result = RvLockGet(&lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvPrintf("RvLockRelease: ");
    result = RvLockRelease(&lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    /* Check between threads */

    RvPrintf("RvLockGet: ");
    result = RvLockGet(&lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvThreadConstruct(&th, RvLockTestThread, &lock);
    RvThreadCreate(&th);
    RvThreadStart(&th);

    RvPrintf("Waiting for 5 seconds.\n");
    RvThreadNanosleep(RvInt64Const(5000000000));

    RvPrintf("RvLockRelease: ");
    result = RvLockRelease(&lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvPrintf("Waiting for 5 seconds.\n");
    RvThreadNanosleep(RvInt64Const(5000000000));

    RvPrintf("Trying to Lock ...\n");
    result = RvLockGet(&lock);
    if(result != RV_OK) {
        RvPrintf("  RvLockGet: ");
        RvLockPrintError(result);
    } else RvPrintf("  RvLockGet: OK\n");

    RvPrintf("RvLockRelease: ");
    result = RvLockRelease(&lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvThreadDestruct(&th);

    RvPrintf("RvLockDestruct: ");
    result = RvLockDestruct(&lock);
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvThreadEnd();
    RvMemoryEnd();

    RvPrintf("RvLockEnd: ");
    result = RvLockEnd();
    if(result != RV_OK) {
        RvLockPrintError(result);
    } else RvPrintf("OK\n");

    RvSemaphoreEnd();
}
#endif /* RV_TEST_CODE */

⌨️ 快捷键说明

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