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

📄 rvsemaphore.c

📁 基于h323协议的软phone
💻 C
字号:
/***********************************************************************
Filename   : rvsemaphore.c
Description: counting sempahore functions
************************************************************************
        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 "rvsemaphore.h"
#include <string.h>

#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_POSIX)
#include <errno.h>
#endif

/* define the default attributes since they may be a structure */
static RvSemaphoreAttr RvDefaultSemaphoreAttr = RV_SEMAPHORE_ATTRIBUTE_DEFAULT;

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

RvStatus RvSemaphoreInit(void)
{
    return RV_OK;
}

RvStatus RvSemaphoreEnd(void)
{
    return RV_OK;
}

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

/* startcount needs to be <= a signed 32 bit number for compatability */
RvStatus RvSemaphoreConstruct(RvSemaphore *sema, RvUint32 startcount)
{
#if defined(RV_NULLCHECK)
    if(sema == NULL)
        return RvSemaphoreErrorCode(RV_ERROR_NULLPTR);
#endif
#if defined(RV_RANGECHECK)
    if(startcount > RV_INT32_MAX)
        return RvSemaphoreErrorCode(RV_ERROR_OUTOFRANGE);
#endif

#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_POSIX)
    if(sem_init(sema, RvDefaultSemaphoreAttr, startcount) < 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_VXWORKS)
    *sema = semCCreate(RvDefaultSemaphoreAttr, (int)startcount);
    if(*sema == NULL)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_PSOS)
    if(sm_create("rv", (unsigned long)startcount, RvDefaultSemaphoreAttr | SM_UNBOUNDED, sema) != 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_OSE)
    *sema = create_sem((OSSEMVAL)startcount); /* No error returns from OSE */
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_NUCLEUS)
    if(NU_Create_Semaphore(sema, "rv", startcount, RvDefaultSemaphoreAttr) != NU_SUCCESS)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_WIN32)
    *sema = CreateSemaphore(NULL, (LONG)startcount, RV_INT32_MAX, NULL);
    if(*sema == NULL)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
    return RV_OK;
}

RvStatus RvSemaphoreDestruct(RvSemaphore *sema)
{
#if defined(RV_NULLCHECK)
    if(sema == NULL)
        return RvSemaphoreErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_POSIX)
    if(sem_destroy(sema) < 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_VXWORKS)
    if(semDelete(*sema) != OK)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_PSOS)
    if(sm_delete(*sema) != 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_OSE)
    kill_sem(*sema); /* no return code */
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_NUCLEUS)
    if(NU_Delete_Semaphore(sema) != NU_SUCCESS)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_WIN32)
    if(CloseHandle(*sema) == 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
    return RV_OK;
}

/* Increment semaphore. Must be callable from non-threads and */
/* non-blocking. */
RvStatus RvSemaphorePost(RvSemaphore *sema)
{
#if defined(RV_NULLCHECK)
    if(sema == NULL)
        return RvSemaphoreErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_POSIX)
    if(sem_post(sema) < 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_VXWORKS)
    if(semGive(*sema) != OK)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_PSOS)
    if(sm_v(*sema) != 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_OSE)
    signal_sem(*sema); /* OSE doesn't bother returning error codes */
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_NUCLEUS)
    if(NU_Release_Semaphore(sema) != NU_SUCCESS)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_WIN32)
    if(ReleaseSemaphore(*sema, 1, NULL) == 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
    return RV_OK;
}

/* Block until semaphore is available. */
RvStatus RvSemaphoreWait(RvSemaphore *sema)
{
#if defined(RV_NULLCHECK)
    if(sema == NULL)
        return RvSemaphoreErrorCode(RV_ERROR_NULLPTR);
#endif

#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_POSIX)
    /* We must loop if we were awoken by a signal. */
    while(sem_wait(sema) < 0) {
        if(errno != EINTR)
            RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
    }
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_VXWORKS)
    if(semTake(*sema, WAIT_FOREVER) != OK)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_PSOS)
    if(sm_p(*sema, SM_WAIT, 0) != 0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_OSE)
    wait_sem(*sema); /* OSE doesn't bother returning error codes */
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_NUCLEUS)
    if(NU_Obtain_Semaphore(sema, NU_SUSPEND) != NU_SUCCESS)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
#if (RV_SEMAPHORE_TYPE == RV_SEMAPHORE_WIN32)
    if(WaitForSingleObject(*sema, INFINITE) != WAIT_OBJECT_0)
        return RvSemaphoreErrorCode(RV_ERROR_UNKNOWN);
#endif
    return RV_OK;
}

RvStatus RvSemaphoreSetAttr(RvSemaphoreAttr *attr)
{
    if(attr != NULL) {
        memcpy(&RvDefaultSemaphoreAttr, attr, sizeof(RvDefaultSemaphoreAttr));
    }
    return RV_OK;
}

#endif /* NONE */

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

#define RV_SEMAPHORE_TEST_COUNT RvUint32Const(10)

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

void RvSemaphoreTestThread(RvThread *th, void *data)
{
    RvSemaphore *sema;
    RvStatus result;
    RvUint32 i, errcount;

    sema = (RvSemaphore *)data;

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

    RvPrintf("Thread: Waiting for Semaphore...\n");
    result = RvSemaphoreWait(sema);
    if(result != RV_OK) {
        RvPrintf("  Thread: RvSemaphoreWait ");
        RvSemaphorePrintError(result);
    } else RvPrintf("  Thread: RvSemaphoreWait OK\n");

    RvPrintf("Thread: Waiting %u times...\n", RV_SEMAPHORE_TEST_COUNT);
    errcount = RvUint32Const(0);
    for(i = RvUint32Const(0); i < RV_SEMAPHORE_TEST_COUNT; i++) {
        result = RvSemaphoreWait(sema);
        if(result != RV_OK)
            errcount++;
    }
    if(errcount > RvUint32Const(0)) {
        RvPrintf("Thread: %u errors on RvSemaphoreWait\n", errcount);
    } else RvPrintf("  Thread: RvSemaphoreWaits OK.\n");

    RvPrintf("Thread: RvSemaphorePost: ");
    result = RvSemaphorePost(sema);
    if(result != RV_OK) {
        RvSemaphorePrintError(result);
    } else RvPrintf("OK\n");

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

    RvPrintf("Thread: Posting %u times...\n", RV_SEMAPHORE_TEST_COUNT);
    errcount = RvUint32Const(0);
    for(i = RvUint32Const(0); i < RV_SEMAPHORE_TEST_COUNT; i++) {
        result = RvSemaphorePost(sema);
        if(result != RV_OK)
            errcount++;
    }
    if(errcount > RvUint32Const(0)) {
        RvPrintf("Thread: %u errors on RvSemaphorePost\n", errcount);
    } else RvPrintf("  Thread: RvSemaphorePosts OK.\n");

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

/* This test uses rvthread which uses us but its the */
/* best we can do, so test appropriately. */
void RvSemaphoreTest(void)
{
    RvStatus result;
    RvSemaphore sema;
    RvThread th;
    RvUint32 i, errcount;

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


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

    RvPrintf("RvSemaphoreConstruct(%d): ", RV_SEMAPHORE_TEST_COUNT);
    result = RvSemaphoreConstruct(&sema, RV_SEMAPHORE_TEST_COUNT);
    if(result != RV_OK) {
        RvSemaphorePrintError(result);
    } else RvPrintf("OK\n");

    RvPrintf("RvSemaphorePost: ");
    result = RvSemaphorePost(&sema);
    if(result != RV_OK) {
        RvSemaphorePrintError(result);
    } else RvPrintf("OK\n");

    RvPrintf("RvSemaphoreWait: ");
    result = RvSemaphoreWait(&sema);
    if(result != RV_OK) {
        RvSemaphorePrintError(result);
    } else RvPrintf("OK\n");

    RvPrintf("Waiting %u times...\n", RV_SEMAPHORE_TEST_COUNT);
    errcount = RvUint32Const(0);
    for(i = RvUint32Const(0); i < RV_SEMAPHORE_TEST_COUNT; i++) {
        result = RvSemaphoreWait(&sema);
        if(result != RV_OK)
            errcount++;
    }
    if(errcount > RvUint32Const(0)) {
        RvPrintf("Error: %u errors on RvSemaphoreWait\n", errcount);
    } else RvPrintf("  RvSemaphoreWaits OK.\n");

    /* Check between threads */

    RvThreadConstruct(&th, RvSemaphoreTestThread, &sema);
    RvThreadCreate(&th);
    RvThreadStart(&th);

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

    RvPrintf("RvSemaphorePost: ");
    result = RvSemaphorePost(&sema);
    if(result != RV_OK) {
        RvSemaphorePrintError(result);
    } else RvPrintf("OK\n");

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

    RvPrintf("Posting %u times...\n", RV_SEMAPHORE_TEST_COUNT);
    errcount = RvUint32Const(0);
    for(i = RvUint32Const(0); i < RV_SEMAPHORE_TEST_COUNT; i++) {
        result = RvSemaphorePost(&sema);
        if(result != RV_OK)
            errcount++;
    }
    if(errcount > RvUint32Const(0)) {
        RvPrintf("Error: %u errors on RvSemaphorePost\n", errcount);
    } else RvPrintf("  RvSemaphorePosts OK.\n");

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

    RvPrintf("Waiting for Semaphore...\n");
    result = RvSemaphoreWait(&sema);
    if(result != RV_OK) {
        RvPrintf("  RvSemaphoreWait ");
        RvSemaphorePrintError(result);
    } else RvPrintf("  RvSemaphoreWait OK\n");

    RvPrintf("Waiting %u times...\n", RV_SEMAPHORE_TEST_COUNT);
    errcount = RvUint32Const(0);
    for(i = RvUint32Const(0); i < RV_SEMAPHORE_TEST_COUNT; i++) {
        result = RvSemaphoreWait(&sema);
        if(result != RV_OK)
            errcount++;
    }
    if(errcount > RvUint32Const(0)) {
        RvPrintf("Error: %u errors on RvSemaphoreWait\n", errcount);
    } else RvPrintf("  RvSemaphoreWaits OK.\n");

    RvThreadDestruct(&th);

    RvPrintf("RvSemaphoreDestruct: ");
    result = RvSemaphoreDestruct(&sema);
    if(result != RV_OK) {
        RvSemaphorePrintError(result);
    } else RvPrintf("OK\n");

    RvThreadEnd();
    RvMemoryEnd();
    RvLockEnd();

    RvPrintf("RvSemaphoreEnd: ");
    result = RvSemaphoreEnd();
    if(result != RV_OK) {
        RvSemaphorePrintError(result);
    } else RvPrintf("OK\n");
}
#endif /* RV_TEST_CODE */

⌨️ 快捷键说明

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