Files
m241Neelima/vxworks-6.9/target/h/spinLockLib.h
T
2026-07-30 11:19:44 +05:30

336 lines
10 KiB
C

/* spinLockLib.h - spin lock library definitions header */
/*
* Copyright (c) 2006-2007, 2009-2010, 2012 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River License agreement.
*/
/*
modification history
--------------------
01q,23may12,cww Removed unnecessary spinLockCpuState arrays from UP systems
(WIND00350319)
01p,27apr10,cww LP64 adaptation
01o,30oct09,gls added build warning when ND spinlocks used when DETERMINISTIC
VSB used (WIND00188965)
01n,01sep09,gls aligned nextTicket to the architecture defined value
for atomic operations (WIND00136154)
01m,11feb09,gls added non-deterministic, timed spinlock support
01l,29nov07,h_k added SPIN_LOCK_ACKNOWLEDGED. (CQ:111571)
01l,30nov07,bha merge for Q3 release
01k,26oct07,dlk Address WIND00109150.
01j,14aug07,dlk In SPIN_LOCK_TRACE case, pass file/line arguments after
lock to lessen problems with modules that don't know about
these arguments. Also, add one layer of braces in
SPIN_LOCK_ISR_DECL initializer to avoid compiler warning.
Also, add pTcb member to struct rtSpinlock for optimization.
01i,13aug07,mmi update spinLockTask structure for ticket-lock implementation
01h,27jun07,gls added S_spinLockLib_NOT_SPIN_LOCK_CALLABLE
added SPIN_LOCK_RESTRICT()
01g,14jun07,rfr Optimize size of ISR spinlocks
01f,04apr07,rfr Added Realtime Spinlocks
01e,29mar07,h_k removed spinLockIsrSingleTake and Give.
01d,08mar07,mmi add SPIN_LOCK_TRACE
01c,10jan07,h_k added spinLockIsrSingleTake and spinLockIsrSingleGive.
01b,15dec06,mmi fixed SPIN_LOCK_ISR_DECL
01b,11dec06,mmi add trace utility
01a,01nov06,mmi written
*/
#ifndef __INCspinLockLibh
#define __INCspinLockLibh
#include <vsbConfig.h>
#include <vwModNum.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
#define S_spinLockLib_NOT_SPIN_LOCK_CALLABLE (M_spinLockLib | 1)
#define S_spinLockLib_INVALID_OPERATION (M_spinLockLib | 2)
#define S_spinLockLib_LOCK_IN_RECOVERY (M_spinLockLib | 3)
#define S_spinLockLib_LOCK_UNAVAILABLE (M_spinLockLib | 4)
#define S_spinLockLib_LOCK_TIMEOUT (M_spinLockLib | 5)
/*
* Return ERROR and set errno if a spinlock is held in the context of the
* running CPU.
*/
#define SPIN_LOCK_RESTRICT() spinLockRestrict()
/*
* The following definition SPIN_LOCK_TRACE can be uncommented to add useful
* debugging information to the spinlock data structure. Currently, this
* information includes the file and line number from which the
* spinLockIsrTake () or spinLockTaskTake () was invoked.
*
* IMPORTANT: Note that all archives must be rebuilt if SPIN_LOCK_TRACE is
* defined.
*/
#if 0
#define SPIN_LOCK_TRACE
#endif
/*
* Abstract the underline API to dynamically expand the appropriate code if
* debugging is enabled for spinLock libraries.
*
* It is assumed that C code never invokes spinLockTaskTake () nor
* spinLockIsrTake () directly. Use of the macros below ensures that
* spinLockXXXTake will be called with the correct parameters.
*/
#define SPIN_LOCK_ISR_INIT(x, y) (spinLockIsrInit(x, y))
#ifdef SPIN_LOCK_TRACE /* trace the file and line number for debugging */
# define SPIN_LOCK_ISR_TAKE(x) (spinLockIsrTake (x, __FILE__, __LINE__))
#else
# define SPIN_LOCK_ISR_TAKE(x) (spinLockIsrTake (x) )
#endif /* SPIN_LOCK_TRACE */
#define SPIN_LOCK_ISR_GIVE(x) (spinLockIsrGive (x) )
#define SPIN_LOCK_TASK_INIT(x, y) (spinLockTaskInit(x, y))
#ifdef SPIN_LOCK_TRACE /* trace the file and line number for debugging */
#define SPIN_LOCK_TASK_TAKE(x) (spinLockTaskTake (x, __FILE__, __LINE__))
#else
#define SPIN_LOCK_TASK_TAKE(x) (spinLockTaskTake (x) )
#endif /* SPIN_LOCK_TRACE */
#define SPIN_LOCK_TASK_GIVE(x) (spinLockTaskGive (x) )
/*
* Note that these macros are not doing any error checking when SPIN_LOCK_TRACE
* It's recommended to use the SPIN_LOCK_XXX_INIT () instead if error checking
* is required
*/
#ifdef SPIN_LOCK_TRACE
#define SPIN_LOCK_TASK_DECL(x, flag) \
spinlockTask_t x = { {{0}}, 0, NULL, -1, flag, NULL, 0}
#ifdef _WRS_CONFIG_SMP
#define SPIN_LOCK_ISR_DECL(x,flag) \
spinlockIsr_t x = { {-1, 0, NULL, 0, {{0}}}, flag, NULL, 0}
#else
#define SPIN_LOCK_ISR_DECL(x,flag) \
spinlockIsr_t x = { {-1, 0}, flag, NULL, 0}
#endif /* _WRS_CONFIG_SMP */
#else /* SPIN_LOCK_TRACE */
#define SPIN_LOCK_TASK_DECL(x, flag) \
spinlockTask_t x = { {{0}}, 0, NULL, -1, flag}
#ifdef _WRS_CONFIG_SMP
#define SPIN_LOCK_ISR_DECL(x, flag) \
spinlockIsr_t x = { {-1, 0, NULL, 0, {{0}}}, flag}
#else
#define SPIN_LOCK_ISR_DECL(x, flag) \
spinlockIsr_t x = { {-1, 0}, flag}
#endif /* _WRS_CONFIG_SMP */
#endif /* SPIN_LOCK_TRACE */
/* Realtime spinlocks */
#define SPIN_LOCK_EMPTY 0
#define SPIN_LOCK_BUSY 1
#define SPIN_LOCK_INTERESTED 2
#define SPIN_LOCK_ACKNOWLEDGED 3
#define SPIN_LOCK_NOBODY -1
typedef struct
{
atomic32_t flag; /* State of this CPU's take of this spinlock */
unsigned int misses; /* The number of times this CPU has been missed */
unsigned int nest; /* number entities attempting a take on this CPU */
#ifdef _WRS_CONFIG_LP64
UINT32 pad; /* explicit pad for 64-bit alignment */
#endif
} spinLockCpuState;
typedef struct
{
atomic32_t owner; /* CPU index of owner */
int key; /* The int key for this lock */
#ifdef _WRS_CONFIG_SMP
void * pTcb;
int intsDone; /* This CPU processed interrupts during */
/* its take */
spinLockCpuState cpu[VX_MAX_SMP_CPUS];
#endif
} rtSpinlock;
/* time limited spin lock */
#define SPINLOCK_OPERATION_OK 0
#define SPINLOCK_OPERATION_ABORTED -1
#define SPINLOCK_TAKE_RECOVERY -2
typedef struct spinLockNdTimedKey_s
{
UINT64 iterCnt64;
atomic32_t state;
int key;
UINT16 prevOwnerId;
} spinLockNdTimedKey_t;
typedef struct spinLockNdTimed_s
{
atomic32_t state;
int options;
UINT64 iterCnt64;
UINT64 timeLimitSec;
UINT64 timeLimitNsec;
} spinLockNdTimed_t;
/* ISR-callable spinlock data type */
typedef struct spinlockIsr
{
rtSpinlock lock;
int flags; /* Reserved for system use */
#ifdef SPIN_LOCK_TRACE
int line;
char * file;
#endif
} spinlockIsr_t;
/*
* ATOMIC_ALIGN_SIZE should be defined by the architecture as the alignment
* value necessary to prevent disruption of an atomic operation due to
* access to memory locations other than the atomic value aligned to this
* value. For many load reserved/store conditional architectures this is
* simply the cache line size.
*
* Currently this defaults to 128 if ATOMIC_ALIGN_SIZE is not defined. This
* value is the largest cache line size on all supported architectures.
*/
#ifndef ATOMIC_ALIGN_SIZE
#define _WRS_LOCK_ALIGN_ticket 128
#else
#define _WRS_LOCK_ALIGN_ticket ATOMIC_ALIGN_SIZE
#endif
/* task-only spinLock data type */
typedef struct spinlockTask
{
union
{
/*
* WIND00136154
*
* Added alignment of the ticket to the architecture defined value
* that ensures atomic operations are not disturbed by access to other
* locations. For many load reserved/store conditional architectures
* this is simply a cache line.
*/
char pad [_WRS_LOCK_ALIGN_ticket];
atomic_t nextTicket; /* ticket for next canditate */
} nextTicketAligned;
atomic_t ticketInService; /* current ticket being served */
void * pTcb;
atomic32Val_t cpuIndex; /* cached cpu ID */
int flags; /* Reserved for system use */
# ifdef SPIN_LOCK_TRACE
char * file; /* cache which file we take lock */
int line; /* cache the line number */
# endif
} spinlockTask_t;
#ifdef SPIN_LOCK_TRACE
typedef void (*SPIN_LOCK_ISR_TAKE_FUNC) (spinlockIsr_t * lock, char * file,
int line);
typedef void (*SPIN_LOCK_TASK_TAKE_FUNC) (spinlockTask_t * lock, char * file,
int line);
#else
typedef void (*SPIN_LOCK_ISR_TAKE_FUNC) (spinlockIsr_t * lock);
typedef void (*SPIN_LOCK_TASK_TAKE_FUNC) (spinlockTask_t * lock);
#endif /* SPIN_LOCK_TRACE */
/* Function prototypes */
extern STATUS spinLockRestrict (void);
/* ISR callable spinLocks functions */
extern void spinLockIsrInit (spinlockIsr_t * lock, int flags);
extern void spinLockIsrGive (spinlockIsr_t * lock);
#ifdef SPIN_LOCK_TRACE
extern void spinLockIsrTake (spinlockIsr_t * lock, char * file, int line);
#else
extern void spinLockIsrTake (spinlockIsr_t * lock);
#endif
/* task callable spinLock functions */
extern void spinLockTaskInit (spinlockTask_t * lock, int flags);
extern void spinLockTaskGive (spinlockTask_t * lock);
#ifdef SPIN_LOCK_TRACE
extern void spinLockTaskTake (spinlockTask_t * lock, char * file, int line);
#else
extern void spinLockTaskTake (spinlockTask_t * lock);
#endif /* SPIN_LOCK_TRACE */
/* time limited spin lock */
#ifdef _WRS_CONFIG_DETERMINISTIC
extern void spinLockNdTimedInit (spinLockNdTimed_t * lock,
struct timespec * pTimeLimit,
int options)
_WRS_USAGE_WARNING("since system has been configured for " \
"determinism: VSB option DETERMINISTIC = 'y'");
extern int spinLockNdTimedGive (spinLockNdTimed_t * lock, UINT16 nodeId,
spinLockNdTimedKey_t * pKey)
_WRS_USAGE_WARNING("since system has been configured for " \
"determinism: VSB option DETERMINISTIC = 'y'");
extern int spinLockNdTimedTake (spinLockNdTimed_t * lock, UINT16 nodeId,
struct timespec * pTimeout,
spinLockNdTimedKey_t * pKey)
_WRS_USAGE_WARNING("since system has been configured for " \
"determinism: VSB option DETERMINISTIC = 'y'");
extern UINT16 spinLockNdTimedPrevOwnerGet (spinLockNdTimedKey_t * pKey)
_WRS_USAGE_WARNING("since system has been configured for " \
"determinism: VSB option DETERMINISTIC = 'y'");
#else
extern void spinLockNdTimedInit (spinLockNdTimed_t * lock,
struct timespec * pTimeLimit,
int options);
extern int spinLockNdTimedGive (spinLockNdTimed_t * lock, UINT16 nodeId,
spinLockNdTimedKey_t * pKey);
extern int spinLockNdTimedTake (spinLockNdTimed_t * lock, UINT16 nodeId,
struct timespec * pTimeout,
spinLockNdTimedKey_t * pKey);
extern UINT16 spinLockNdTimedPrevOwnerGet (spinLockNdTimedKey_t * pKey);
#endif /* _WRS_CONFIG_DETERMINISTIC */
#ifdef __cplusplus
}
#endif
#endif /* __INCspinLockLibh */