original files of m241
This commit is contained in:
@@ -0,0 +1,719 @@
|
||||
/* semRWLibInlineP.h - inline reader/writer semaphore library header file */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute or otherwise make use of this software
|
||||
* may be licensed only pursuant to the terms of an applicable Wind River
|
||||
* license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01a,27jun13,dlk written.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module is experimental and private. The interfaces it defines
|
||||
* are subject to change without notice.
|
||||
*
|
||||
* Inline implementation of reader/writer semaphores, (somewhat) scalable
|
||||
* according to provided semaphore options. Initially only "minimal" and
|
||||
* "fully featured" option combinations may be supported.
|
||||
*
|
||||
* These inline reader/writer semaphore APIs are supported only in the
|
||||
* kernel, not from RTPs.
|
||||
*/
|
||||
|
||||
#ifndef __INCsemRWLibInlinePh
|
||||
#define __INCsemRWLibInlinePh
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <semLib.h>
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#include <vsbConfig.h>
|
||||
#include <stdarg.h>
|
||||
#include <intLib.h>
|
||||
#include <errnoLib.h>
|
||||
|
||||
/*
|
||||
* The following private header files are necessary for the implementation of
|
||||
* the inline APIs. The contents of these files are subject to change without
|
||||
* notice.
|
||||
*/
|
||||
|
||||
#include <private/qLibP.h>
|
||||
#include <private/semLibP.h>
|
||||
#include <private/windLibP.h>
|
||||
#include <private/kernelLibP.h>
|
||||
|
||||
#ifndef _WRS_CONFIG_SMP
|
||||
#include <private/sigLibP.h>
|
||||
#include <private/intLibP.h>
|
||||
#endif /* WRS_CONFIG_SMP */
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
/*
|
||||
* Additional pseudo-options (not stored in semId->options).
|
||||
* These must not conflict in value with the options defined in semLibCommon.h.
|
||||
* Start from the most-significant bit and work down.
|
||||
*/
|
||||
|
||||
#define SEM_RW_WRITER_CALL ((int)0x80000000)
|
||||
#define SEM_RW_READER_CALL (0x40000000)
|
||||
|
||||
/* option masks for Reader-Writer semaphores*/
|
||||
|
||||
#define SEM_RW_OPTIONS_MASK_INLINE (SEM_Q_FIFO | \
|
||||
SEM_Q_PRIORITY | \
|
||||
SEM_DELETE_SAFE | \
|
||||
SEM_INVERSION_SAFE | \
|
||||
SEM_EVENTSEND_ERR_NOTIFY | \
|
||||
SEM_INTERRUPTIBLE | \
|
||||
SEM_NO_ID_VALIDATE | \
|
||||
SEM_NO_ERROR_CHECK | \
|
||||
SEM_NO_EVENT_SEND | \
|
||||
SEM_NO_SYSTEM_VIEWER | \
|
||||
SEM_NO_RECURSE)
|
||||
|
||||
/*
|
||||
* 'Minimal' reader-writer semaphores have a fast-path that allows
|
||||
* them to be given or taken (under certain conditions) without entering
|
||||
* the kernel and without fetching the current task ID, but they do not
|
||||
* support deletion safety, inversion safety, recursive taking, or VxWorks
|
||||
* event sending. Some positive options must be disallowed, and some
|
||||
* 'negative' options must be enabled.
|
||||
*/
|
||||
#define SEM_RW_OPTIONS_MIN_DISALLOWED (SEM_DELETE_SAFE | \
|
||||
SEM_INVERSION_SAFE | \
|
||||
SEM_EVENTSEND_ERR_NOTIFY)
|
||||
/*
|
||||
* Required (negative) options for minimal implementation.
|
||||
* - Supporting recursion requires the reader task table (or a different API)
|
||||
* - Object ID validation requires object lock (entering the kernel in SMP)
|
||||
* - Don't want to support EVENT_SEND.
|
||||
*/
|
||||
#define SEM_RW_OPTIONS_MIN_REQUIRED (SEM_NO_RECURSE | \
|
||||
SEM_NO_EVENT_SEND | \
|
||||
SEM_NO_ID_VALIDATE)
|
||||
|
||||
#define SEM_RW_OPTIONS_ARE_MINIMAL(x) \
|
||||
(((x) & SEM_RW_OPTIONS_MIN_DISALLOWED) == 0 && \
|
||||
((x) & SEM_RW_OPTIONS_MIN_REQUIRED) == SEM_RW_OPTIONS_MIN_REQUIRED)
|
||||
|
||||
#if !defined (_ASMLANGUAGE)
|
||||
|
||||
enum SEM_RW_MODE
|
||||
{
|
||||
SEM_RW_MODE_UNOWNED = 0,
|
||||
SEM_RW_MODE_READ,
|
||||
SEM_RW_MODE_WRITE
|
||||
};
|
||||
|
||||
#define SEM_RW_INLINE_NDEBUG
|
||||
|
||||
#ifdef SEM_RW_INLINE_NDEBUG
|
||||
#define semrw_kassert(ignore) ((void) 0)
|
||||
#else /* turn debugging on */
|
||||
|
||||
#include <logLib.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#define _SEMRW_KASSERT_STR(z) _SEMRW_KASSERT_TMP(z)
|
||||
#define _SEMRW_KASSERT_TMP(z) #z
|
||||
|
||||
extern void __semrw_kassert (const char *msg);
|
||||
|
||||
#define semrw_kassert(test) \
|
||||
((void) \
|
||||
((test) ? ((void) 0) : \
|
||||
__semrw_kassert("Assertion failed: "#test", file " \
|
||||
__FILE__ ", line "_SEMRW_KASSERT_STR(__LINE__)"\n")))
|
||||
#endif /* SEM_RW_INLINE_NDEBUG */
|
||||
|
||||
/* function declarations (support routines in semRWMinLib.c) */
|
||||
|
||||
extern STATUS semRMinTakeHard (SEM_ID semId, int options);
|
||||
extern STATUS semWMinTakeHard (SEM_ID semId, int options);
|
||||
extern STATUS semRMinGiveHard (SEM_ID semId, int options);
|
||||
extern STATUS semWMinGiveHard (SEM_ID semId, int options);
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* _semRWIsrCheck - return ERROR if called from an ISR
|
||||
*
|
||||
* Returns OK if not called from an ISR, otherwise sets cpu-specific
|
||||
* errno value and returns ERROR.
|
||||
*
|
||||
* RETURNS: OK or ERROR
|
||||
* ERRNO: S_intLib_NOT_ISR_CALLABLE
|
||||
* NOMANUAL
|
||||
*/
|
||||
_WRS_INLINE STATUS _semRWIsrCheck (void)
|
||||
{
|
||||
#ifdef _WRS_CONFIG_SMP
|
||||
|
||||
int cpuid;
|
||||
int intCnt;
|
||||
int level;
|
||||
|
||||
level = KERNEL_INT_CPU_LOCK();
|
||||
cpuid = _WRS_CPU_INDEX_GET ();
|
||||
intCnt = _WRS_KERNEL_CPU_GLOBAL_GET (cpuid, intCnt);
|
||||
if (intCnt != 0)
|
||||
{
|
||||
_WRS_KERNEL_CPU_GLOBAL_SET (cpuid, errno, S_intLib_NOT_ISR_CALLABLE);
|
||||
}
|
||||
KERNEL_INT_CPU_UNLOCK(level);
|
||||
|
||||
return intCnt ? ERROR : 0;
|
||||
|
||||
#else /* ! _WRS_CONFIG_SMP */
|
||||
|
||||
return _WRS_INT_RESTRICT ();
|
||||
|
||||
#endif /* !_WRS_CONFIG_SMP */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* _semRMinGive_inline - give a minimal reader/writer semaphore in read mode
|
||||
*
|
||||
* This routine is internal and should not be called directly.
|
||||
*
|
||||
* It handles the case of a call to semRWGive_inline() with 'minimal'
|
||||
* options by a reader task owning the semaphore.
|
||||
*
|
||||
* RETURNS: OK
|
||||
* ERRNO: N/A
|
||||
* \is
|
||||
* \ie
|
||||
* NOMANUAL
|
||||
*/
|
||||
|
||||
_WRS_INLINE STATUS _semRMinGive_inline
|
||||
(
|
||||
SEM_ID semId, /* semaphore ID to give */
|
||||
int options /* semaphore options */
|
||||
)
|
||||
{
|
||||
atomic32_t *pSemVal = &SEM_RWMIN_VALUE(semId);
|
||||
atomic32Val_t v;
|
||||
|
||||
/* Note, the required memory barrier was done in semRWGive_inline(). */
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
v = vxAtomic32Get_inline (pSemVal);
|
||||
|
||||
semrw_kassert ((v & SEM_RWMIN_VAL_W_OWNS) == 0);
|
||||
semrw_kassert ((v & ~SEM_RWMIN_VAL_PEND) != 0);
|
||||
|
||||
/*
|
||||
* Note, this is the only case were *pSemVal may be legitimately
|
||||
* modified outside of obj/kernel lock when SEM_RWMIN_VAL_PEND is set:
|
||||
* a reader-owner other than the last reader-owner may decrement the
|
||||
* reader count when giving the semaphore.
|
||||
*/
|
||||
if (v == (SEM_RWMIN_VAL_R_INC | SEM_RWMIN_VAL_PEND))
|
||||
break;
|
||||
if (vxAtomic32Cas (pSemVal, v, v - SEM_RWMIN_VAL_R_INC))
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the last reader-owner and there are tasks pended.
|
||||
* Have to enter the kernel.
|
||||
*/
|
||||
return semRMinGiveHard (semId, options);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* _semWMinGive_inline - give a minimal reader/writer semaphore in write mode
|
||||
*
|
||||
* This routine is internal and should not be called directly.
|
||||
*
|
||||
* It handles the case of a call to semRWGive_inline() with 'minimal'
|
||||
* options by a writer task owning the semaphore.
|
||||
*
|
||||
* RETURNS: OK
|
||||
* ERRNO: N/A
|
||||
* \is
|
||||
* \ie
|
||||
* NOMANUAL
|
||||
*/
|
||||
|
||||
_WRS_INLINE STATUS _semWMinGive_inline
|
||||
(
|
||||
SEM_ID semId, /* semaphore ID to give */
|
||||
int options /* semaphore options */
|
||||
)
|
||||
{
|
||||
atomic32_t *pSemVal = &SEM_RWMIN_VALUE(semId);
|
||||
atomic32Val_t v;
|
||||
|
||||
/* The required memory barrier was done in semRWGive_inline() */
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
v = vxAtomic32Get_inline (pSemVal);
|
||||
|
||||
semrw_kassert ((v & SEM_RWMIN_VAL_W_OWNS) != 0);
|
||||
semrw_kassert ((v & ~(SEM_RWMIN_VAL_PEND|SEM_RWMIN_VAL_W_OWNS)) == 0);
|
||||
|
||||
if ((v & SEM_RWMIN_VAL_PEND) != 0)
|
||||
break;
|
||||
if (vxAtomic32Cas (pSemVal, v, 0))
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* There are tasks pended. Have to enter the kernel. */
|
||||
|
||||
return semWMinGiveHard (semId, options);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* semRWGive_inline - give a reader/writer semaphore (inline version)
|
||||
*
|
||||
* This routine gives a reader/writer semaphore.
|
||||
*
|
||||
* The behavior of this routine is similar to that of semRWGive() on a
|
||||
* reader/writer semaphore, differing in that an additional parameter,
|
||||
* <options>, must be specified. The <options> parameter allows scaling
|
||||
* support for particular semaphore features out of the call to this routine.
|
||||
*
|
||||
* The semaphore specified by <semId> must be of the reader/writer type.
|
||||
*
|
||||
* The options specified by <options> are called 'minimal' if the following
|
||||
* options are not enabled:
|
||||
* SEM_DELETE_SAFE
|
||||
* SEM_INVERSION_SAFE
|
||||
* SEM_EVENTSEND_ERR_NOTIFY
|
||||
* and the following (negative) options are enabled:
|
||||
* SEM_NO_RECURSE
|
||||
* SEM_NO_EVENT_SEND
|
||||
* SEM_NO_ID_VALIDATE
|
||||
*
|
||||
* If the options are 'minimal', one of the special pseudo-options
|
||||
* SEM_RW_READER_CALL or SEM_RW_WRITER_CALL may also be specified to omit
|
||||
* (compile out) the dynamic test of whether the semaphore is currently
|
||||
* reader-owned or writer-owned, provided the calling code knows this.
|
||||
*
|
||||
* For best scalability, this inline routine should be called with
|
||||
* a compile-time-constant options value, so that the compiler may optimize
|
||||
* away inapplicable code branches.
|
||||
*/
|
||||
|
||||
_WRS_INLINE STATUS semRWGive_inline
|
||||
(
|
||||
SEM_ID semId, /* semaphore ID to give */
|
||||
int options /* semaphore options */
|
||||
)
|
||||
{
|
||||
int level;
|
||||
atomic32_t *pSemVal;
|
||||
atomic32Val_t val;
|
||||
|
||||
if ((options & ~(SEM_RW_OPTIONS_MASK_INLINE |
|
||||
SEM_RW_WRITER_CALL | SEM_RW_READER_CALL)) != 0)
|
||||
{
|
||||
errno = S_semLib_INVALID_OPTION;
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
#ifdef _WRS_CONFIG_SV_INSTRUMENTATION
|
||||
if ((options & SEM_NO_SYSTEM_VIEWER) == 0)
|
||||
{
|
||||
_Vx_usr_arg_t owner;
|
||||
_Vx_usr_arg_t recurse;
|
||||
|
||||
if (SEM_RW_OPTIONS_ARE_MINIMAL(options))
|
||||
{
|
||||
/*
|
||||
* Note: We replace semId->semOwner with *pSemVal,
|
||||
* and replace semId->recurse with 0xabadcafe
|
||||
* for minimal semaphores. Hopefully sticking
|
||||
* with EVT_OBJ_3 (used by semGive()) will lead to less
|
||||
* confusion on the system-viewer host side and still
|
||||
* provide useful information, even if a couple of the
|
||||
* event fields are mislabelled in the display.
|
||||
* An alternative might be to introduce a new event type...
|
||||
*/
|
||||
pSemVal = &SEM_RWMIN_VALUE(semId);
|
||||
owner = (_Vx_usr_arg_t)vxAtomic32Get_inline(pSemVal);
|
||||
recurse = (_Vx_usr_arg_t)0xabadcafe;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* In the full-featured case, the generic semGive() code
|
||||
* would emit the object-level EVENT_SEMGIVE. Since
|
||||
* we call semRWGive() directly, we must do it here.
|
||||
*/
|
||||
owner = (_Vx_usr_arg_t)semId->semOwner;
|
||||
recurse = (_Vx_usr_arg_t)semId->recurse;
|
||||
}
|
||||
|
||||
/* system viewer - level 1 event logging */
|
||||
EVT_OBJ_3 (semId, semClassId, EVENT_SEMGIVE, semId, owner, recurse);
|
||||
}
|
||||
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
|
||||
|
||||
|
||||
if (SEM_RW_OPTIONS_ARE_MINIMAL(options))
|
||||
{
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (_semRWIsrCheck() != OK)
|
||||
return ERROR;
|
||||
if (! SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that loads or stores done while holding the lock
|
||||
* are globally seen as occurring before the stores that release
|
||||
* the lock.
|
||||
*/
|
||||
VX_MEM_BARRIER_RW();
|
||||
|
||||
if ((options & (SEM_RW_READER_CALL | SEM_RW_WRITER_CALL)) == 0)
|
||||
{
|
||||
/*
|
||||
* Will have to determine if the caller is a reader or writer
|
||||
* dynamically.
|
||||
*/
|
||||
pSemVal = &SEM_RWMIN_VALUE(semId);
|
||||
val = vxAtomic32Get_inline(pSemVal);
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (0 == (val & ~SEM_RWMIN_VAL_PEND))
|
||||
{
|
||||
/* The semaphore appears unowned. */
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
val = 0;
|
||||
|
||||
if ((options & SEM_RW_WRITER_CALL) != 0
|
||||
|| (val & SEM_RWMIN_VAL_W_OWNS) != 0)
|
||||
return _semWMinGive_inline (semId, options & ~SEM_RW_WRITER_CALL);
|
||||
else
|
||||
return _semRMinGive_inline (semId, options & ~SEM_RW_READER_CALL);
|
||||
}
|
||||
else /* non-minimal options */
|
||||
{
|
||||
/*
|
||||
* For now, we handle only the full-featured case by calling
|
||||
* semRWGive().
|
||||
*/
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
return semRWGive (semId);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* semWTake_inline - take a reader/writer semaphore in write mode (inline version)
|
||||
*
|
||||
* This routine takes a reader/writer semaphore in write mode.
|
||||
*
|
||||
* The behavior of this routine is similar to that of semWTake() on a
|
||||
* reader/writer semaphore, differing in that an additional parameter,
|
||||
* <options>, must be specified. The <options> parameter allows scaling
|
||||
* support for particular semaphore features out of the call to this routine.
|
||||
*
|
||||
* The semaphore specified by <semId> must be of the reader/writer type.
|
||||
*/
|
||||
|
||||
_WRS_INLINE STATUS semWTake_inline
|
||||
(
|
||||
SEM_ID semId, /* semaphore ID to take */
|
||||
_Vx_ticks_t timeout, /* timeout in ticks */
|
||||
int options /* semaphore options */
|
||||
)
|
||||
{
|
||||
if ((options & ~SEM_RW_OPTIONS_MASK_INLINE) != 0)
|
||||
{
|
||||
errno = S_semLib_INVALID_OPTION;
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
if (SEM_RW_OPTIONS_ARE_MINIMAL(options))
|
||||
{
|
||||
atomic32_t *pSemVal = &SEM_RWMIN_VALUE(semId);
|
||||
atomic32Val_t v;
|
||||
|
||||
#ifdef _WRS_CONFIG_SV_INSTRUMENTATION
|
||||
if (0 == (options & SEM_NO_SYSTEM_VIEWER))
|
||||
{
|
||||
/* system viewer - level 1 event logging */
|
||||
/*
|
||||
* Note: We replace semId->semOwner with *pSemVal,
|
||||
* and replace semId->recurse with 0xabadcafe
|
||||
* for minimal semaphores. Hopefully sticking
|
||||
* with EVT_OBJ_3 (used by semWTake()) will lead to less
|
||||
* confusion on the system-viewer host side and still
|
||||
* provide useful information, even if a couple of the
|
||||
* event fields are mislabelled in the display.
|
||||
* An alternative might be to introduce a new event type...
|
||||
*/
|
||||
EVT_OBJ_3 (semId, semClassId, EVENT_SEMWTAKE,
|
||||
semId, *pSemVal, 0xabadcafe);
|
||||
}
|
||||
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
|
||||
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (_semRWIsrCheck() != OK)
|
||||
return ERROR;
|
||||
if (timeout != WAIT_FOREVER || !SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
v = vxAtomic32Get_inline (pSemVal);
|
||||
semrw_kassert ((v & SEM_RWMIN_VAL_W_OWNS) == 0 ||
|
||||
(v & ~(SEM_RWMIN_VAL_W_OWNS | SEM_RWMIN_VAL_PEND)) == 0);
|
||||
|
||||
if (v != 0)
|
||||
break;
|
||||
|
||||
if (vxAtomic32Cas (pSemVal, 0, SEM_RWMIN_VAL_W_OWNS))
|
||||
{
|
||||
VX_INSTR_BARRIER();
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* The semaphore appears to be owned; must enter the kernel. */
|
||||
return semWMinTakeHard (semId, options);
|
||||
}
|
||||
else /* non-minimal options */
|
||||
{
|
||||
/*
|
||||
* For now, we handle only the full-featured case by calling
|
||||
* semWTake().
|
||||
*/
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
return semWTake (semId, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* semRTake_inline - take a reader/writer semaphore in read mode (inline version)
|
||||
*
|
||||
* This routine takes a reader/writer semaphore in read mode.
|
||||
*
|
||||
* The behavior of this routine is similar to that of semRTake() on a
|
||||
* reader/writer semaphore, differing in that an additional parameter,
|
||||
* <options>, must be specified. The <options> parameter allows scaling
|
||||
* support for particular semaphore features out of the call to this routine.
|
||||
*
|
||||
* The semaphore specified by <semId> must be of the reader/writer type.
|
||||
*/
|
||||
|
||||
_WRS_INLINE STATUS semRTake_inline
|
||||
(
|
||||
SEM_ID semId, /* semaphore ID to take */
|
||||
_Vx_ticks_t timeout, /* timeout in ticks */
|
||||
int options /* semaphore options */
|
||||
)
|
||||
{
|
||||
if ((options & ~SEM_RW_OPTIONS_MASK_INLINE) != 0)
|
||||
{
|
||||
errno = S_semLib_INVALID_OPTION;
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
if (SEM_RW_OPTIONS_ARE_MINIMAL(options))
|
||||
{
|
||||
atomic32_t *pSemVal = &SEM_RWMIN_VALUE(semId);
|
||||
atomic32Val_t v;
|
||||
|
||||
#ifdef _WRS_CONFIG_SV_INSTRUMENTATION
|
||||
if (0 == (options & SEM_NO_SYSTEM_VIEWER))
|
||||
{
|
||||
/* system viewer - level 1 event logging */
|
||||
/*
|
||||
* Note: We replace semId->semOwner with *pSemVal,
|
||||
* and replace semId->recurse with 0xabadcafe
|
||||
* for minimal semaphores. Hopefully sticking
|
||||
* with EVT_OBJ_3 (used by semRTake()) will lead to less
|
||||
* confusion on the system-viewer host side and still
|
||||
* provide useful information, even if a couple of the
|
||||
* event fields are mislabelled in the display.
|
||||
* An alternative might be to introduce a new event type...
|
||||
*/
|
||||
EVT_OBJ_3 (semId, semClassId, EVENT_SEMRTAKE,
|
||||
semId, *pSemVal, 0xabadcafe);
|
||||
}
|
||||
#endif /* _WRS_CONFIG_SV_INSTRUMENTATION */
|
||||
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (_semRWIsrCheck() != OK)
|
||||
return ERROR;
|
||||
if (timeout != WAIT_FOREVER || !SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
v = vxAtomic32Get_inline (pSemVal);
|
||||
semrw_kassert ((v & SEM_RWMIN_VAL_W_OWNS) == 0 ||
|
||||
(v & ~(SEM_RWMIN_VAL_W_OWNS | SEM_RWMIN_VAL_PEND)) == 0);
|
||||
|
||||
if ((v & (SEM_RWMIN_VAL_W_OWNS | SEM_RWMIN_VAL_PEND)) != 0)
|
||||
break;
|
||||
|
||||
if (vxAtomic32Cas (pSemVal, v, v + SEM_RWMIN_VAL_R_INC))
|
||||
{
|
||||
VX_INSTR_BARRIER();
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* A writer owns the semaphore, or there are pended tasks. Enter
|
||||
* the kernel. Note that the minimal case code does not
|
||||
* implement timeouts.
|
||||
*/
|
||||
return semRMinTakeHard (semId, options);
|
||||
}
|
||||
else /* non-minimal options */
|
||||
{
|
||||
/* For now, handle the full-featured case by calling semRTake(). */
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
return semRTake (semId, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* semRWMinOwner_inline - return the owner type of a mimimal reader-writer semaphore
|
||||
*
|
||||
* This function returns a value that indicates whether the semaphore
|
||||
* is currently unowned, held by readers, or owned by a single writer.
|
||||
*
|
||||
* WARNING:
|
||||
* The value returned is only valid and stable if the caller is in fact
|
||||
* a task currently owning the semaphore as either a reader or a writer.
|
||||
*
|
||||
* RETURNS:
|
||||
* \is
|
||||
* \i 'SEM_RW_MODE_UNOWNED'
|
||||
* if the semaphore is currently unheld.
|
||||
*
|
||||
* \i 'SEM_RW_MODE_READ'
|
||||
* if the semaphore is held by one or more reader tasks.
|
||||
*
|
||||
* \i 'SEM_RW_MODE_WRITE'
|
||||
* if the semaphore is owned by a writer task.
|
||||
* \ie
|
||||
*/
|
||||
_WRS_INLINE int semRWOwner_inline
|
||||
(
|
||||
SEM_ID semId, /* the RW semaphore */
|
||||
int options /* semaphore options */
|
||||
)
|
||||
{
|
||||
if ((options & ~SEM_RW_OPTIONS_MASK_INLINE) != 0)
|
||||
{
|
||||
errno = S_semLib_INVALID_OPTION;
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
if (SEM_RW_OPTIONS_ARE_MINIMAL(options))
|
||||
{
|
||||
atomic32_t *pSemVal = &SEM_RWMIN_VALUE(semId);
|
||||
atomicVal_t v = vxAtomic32Get_inline (pSemVal);
|
||||
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (! SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (v == 0) /* PEND bit will not be set if un-owned... */
|
||||
return SEM_RW_MODE_UNOWNED; /* no-one owns it */
|
||||
if (v & SEM_RWMIN_VAL_W_OWNS)
|
||||
return SEM_RW_MODE_WRITE; /* writer owns it */
|
||||
return SEM_RW_MODE_READ; /* reader owns it */
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((options & SEM_NO_ERROR_CHECK) == 0)
|
||||
{
|
||||
if (SEM_IS_MINIMAL (semId))
|
||||
{
|
||||
errnoSet (S_semLib_INVALID_OPERATION);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this task is an owner (either read or write) of the semaphore,
|
||||
* then semId->semOwner is stable, even though we have not entered the
|
||||
* kernel.
|
||||
*/
|
||||
if (semId->semOwner != NULL)
|
||||
return SEM_RW_MODE_WRITE;
|
||||
/*
|
||||
* If this task is a read-owner of the semaphore, then
|
||||
* SEMRW_READ_CNT(semId) is stably non-zero.
|
||||
*/
|
||||
if (SEMRW_READ_CNT(semId) != 0)
|
||||
return SEM_RW_MODE_READ;
|
||||
|
||||
return SEM_RW_MODE_UNOWNED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* !defined (_ASMLANGUAGE) */
|
||||
|
||||
#endif /* __INCsemRWLibInlinePh */
|
||||
Reference in New Issue
Block a user