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

322 lines
12 KiB
C

/* vxAtomicArchLib.h - IA32 specific atomic library header */
/*
* Copyright (c) 2006-2010, 2018 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
--------------------
19sep18,m_w make sure the code map of inline ASM under GNU
is correct (VXW6-86665)
13sep10,scm WIND002322578 remove type-punning warnings...
29apr10,pad Moved extern C statement after include statements.
15may09,gls made memory barriers available in user space
28apr09,cww Add fixed size APIs
29aug08,to add inline atomic routines for GCC
16jun08,zl use _WRS_BARRIER() for memory barrier implementations.
17jan08,gls renamed inline routines
03jan08,gls fixed DCC _inline_vxCas()
11dec07,gls Added _inline_vxCas()
29nov06,scm Created
*/
#ifndef __INCvxAtomicArchLibh
#define __INCvxAtomicArchLibh
#include <arch/i86/vxAtomicArchLibCommon.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ASMLANGUAGE
#if defined (__DCC__)
#define VXCAS_COMMON(address, old_value, new_value) \
movl old_value,%eax; /* get old_value to cmp */ \
lock; /* lock the Bus during the next inst */ \
cmpxchg new_value, (address); /* if (%eax == (address) */ \
/* {ZF = 1; (address) = %ecx;} */ \
/* else */ \
/* {ZF = 0; %eax = (address);} */ \
jz 2f; \
movl $0, %eax; /* set status to FALSE */ \
jmp 1f; \
2: \
movl $1, %eax; /* set status to TRUE */ \
1:
__asm volatile BOOL vxAtomicCas_inline (atomic_t * address, atomicVal_t old_value,
atomicVal_t new_value)
{
% reg address; mem old_value; mem new_value;
! "ax", "cx"
movl new_value,%ecx /* get new_value to set */
VXCAS_COMMON (address, old_value, %ecx)
% reg address; mem old_value; reg new_value;
! "ax"
VXCAS_COMMON (address, old_value, new_value)
% mem address; mem old_value; mem new_value;
! "ax", "cx", "dx"
movl new_value,%ecx /* get new_value to set */
movl address,%edx /* get address */
VXCAS_COMMON (%edx, old_value, %ecx)
% mem address; mem old_value; reg new_value;
! "ax", "dx"
movl address,%edx /* get address */
VXCAS_COMMON (%edx, old_value, new_value)
}
__asm volatile BOOL vxAtomic32Cas_inline (atomic32_t * address, atomic32Val_t old_value,
atomic32Val_t new_value)
{
% reg address; mem old_value; mem new_value;
! "ax", "cx"
movl new_value,%ecx /* get new_value to set */
VXCAS_COMMON (address, old_value, %ecx)
% reg address; mem old_value; reg new_value;
! "ax"
VXCAS_COMMON (address, old_value, new_value)
% mem address; mem old_value; mem new_value;
! "ax", "cx", "dx"
movl new_value,%ecx /* get new_value to set */
movl address,%edx /* get address */
VXCAS_COMMON (%edx, old_value, %ecx)
% mem address; mem old_value; reg new_value;
! "ax", "dx"
movl address,%edx /* get address */
VXCAS_COMMON (%edx, old_value, new_value)
}
#define vxCas_inline vxAtomicCas_inline
#define vxAtomicAdd_inline vxAtomicAdd
#define vxAtomic32Add_inline vxAtomic32Add
#define vxAtomicSub_inline vxAtomicSub
#define vxAtomic32Sub_inline vxAtomic32Sub
#define vxAtomicInc_inline vxAtomicInc
#define vxAtomic32Inc_inline vxAtomic32Inc
#define vxAtomicDec_inline vxAtomicDec
#define vxAtomic32Dec_inline vxAtomic32Dec
#define vxAtomicGet_inline vxAtomicGet
#define vxAtomic32Get_inline vxAtomic32Get
#define vxAtomicSet_inline vxAtomicSet
#define vxAtomic32Set_inline vxAtomic32Set
#define vxAtomicClear_inline vxAtomicClear
#define vxAtomic32Clear_inline vxAtomic32Clear
#elif defined (__GNUC__)
static __inline__ BOOL vxAtomic32Cas_inline
(
atomic32_t * target, /* memory location to compare-and-swap */
atomic32Val_t oldValue, /* compare to this value */
atomic32Val_t newValue /* swap with this value */
)
{
BOOL swapped;
__asm__ volatile
(
"movl %3, %%eax;" /* move oldValue to %eax */
"lock;" /* lock the Bus during the next inst */
"cmpxchg %4, %2;" /* if (%eax == *target) */
/* {ZF = 1; *target = newValue;} */
/* else */
/* {ZF = 0; %eax = *target;} */
"setz %%al;" /* if success, set swapped to TRUE else FALSE */
"movzbl %%al, %0" /* zero extend swapped */
: "=&a" (swapped), /* output: swapped is %0 */
"=m" (target) /* target is %1 */
: "m" (*(target)), /* input: *target is %2 */
"g" (oldValue), /* oldValue is %3 */
"r" (newValue) /* newValue is %4 */
: "memory" /* memory clobber for code barrier */
);
return swapped;
}
static __inline__ atomic32Val_t vxAtomic32Add_inline
(
atomic32_t * target,
atomic32Val_t value
)
{
__asm__ volatile
(
"lock;" /* lock the Bus during the next inst */
"xaddl %0, %2" /* TMP = value + *target */
/* value = *target */
/* *target = TMP */
: "+r" (value), /* output: value is %0 */
"=m" (target) /* target is %1 */
: "m" (*(target)) /* input: *target is %2 */
: "memory" /* memory clobber for code barrier */
);
return value;
}
static __inline__ atomic32Val_t vxAtomic32Sub_inline
(
atomic32_t * target,
atomic32Val_t value
)
{
__asm__ volatile
(
"negl %0;" /* Negate value... */
"lock;" /* lock the Bus during the next inst */
"xaddl %0, %2" /* TMP = -value + *target */
/* value = *target */
/* *target = TMP */
: "+r" (value), /* output: value is %0 */
"=m" (target) /* target is %1 */
: "m" (*(target)) /* input: *target is %2 */
: "memory" /* memory clobber for code barrier */
);
return value;
}
static __inline__ atomic32Val_t vxAtomic32Inc_inline
(
atomic32_t * target
)
{
atomic32Val_t value;
__asm__ volatile
(
"movl $1, %0;" /* inc by 1 */
"lock;" /* lock the Bus during the next inst */
"xaddl %0, %2" /* TMP = *target + 1 */
/* value = *target */
/* *target = TMP */
: "=&r" (value), /* output: value is %0 */
"=m" (target) /* target is %1 */
: "m" (*(target)) /* input: *target is %2 */
: "memory" /* memory clobber for code barrier */
);
return value;
}
static __inline__ atomic32Val_t vxAtomic32Dec_inline
(
atomic32_t * target
)
{
atomic32Val_t value;
__asm__ volatile
(
"movl $(-1), %0;" /* dec by 1 */
"lock;" /* lock the Bus during the next inst */
"xaddl %0, %2" /* TMP = *target - 1 */
/* value = *target */
/* *target = TMP */
: "=&r" (value), /* output: value is %0 */
"=m" (target) /* target is %1 */
: "m" (*(target)) /* input: *target is %2 */
: "memory" /* memory clobber for code barrier */
);
return value;
}
static __inline__ atomic32Val_t vxAtomic32Get_inline
(
atomic32_t * target
)
{
atomic32Val_t value;
__asm__ volatile
(
"movl %1, %0" /* get value with bus-lock */
: "=r" (value) /* output: value is %0 */
: "m" (*(target)) /* input: *target is %1 */
: "memory" /* memory clobber for code barrier */
);
return value;
}
static __inline__ atomic32Val_t vxAtomic32Set_inline
(
atomic32_t * target,
atomic32Val_t value
)
{
__asm__ volatile
(
"xchgl %0, %2" /* set value with bus-lock */
: "+r" (value), /* output: value is %0 */
"=m" (target) /* target is %1 */
: "m" (*(target)) /* input: *target is %2 */
: "memory" /* memory clobber for code barrier */
);
return value;
}
static __inline__ atomic32Val_t vxAtomic32Clear_inline
(
atomic32_t * target
)
{
atomicVal_t value;
__asm__ volatile
(
"movl $0, %0;" /* 'clear' value to set */
"xchgl %0, %2" /* swap 'clear' value with bus-lock */
: "=&r" (value), /* output: value is %0 */
"=m" (target) /* target is %1 */
: "m" (*(target)) /* input: *target is %2 */
: "memory" /* memory clobber for code barrier */
);
return value;
}
#define vxCas_inline vxAtomic32Cas_inline
#define vxAtomicCas_inline vxAtomic32Cas_inline
#define vxAtomicAdd_inline vxAtomic32Add_inline
#define vxAtomicSub_inline vxAtomic32Sub_inline
#define vxAtomicInc_inline vxAtomic32Inc_inline
#define vxAtomicDec_inline vxAtomic32Dec_inline
#define vxAtomicGet_inline vxAtomic32Get_inline
#define vxAtomicSet_inline vxAtomic32Set_inline
#define vxAtomicClear_inline vxAtomic32Clear_inline
#else
#define vxCas_inline vxAtomicCas
#define vxAtomicCas_inline vxAtomicCas
#define vxAtomic32Cas_inline vxAtomic32Cas
#define vxAtomicAdd_inline vxAtomicAdd
#define vxAtomic32Add_inline vxAtomic32Add
#define vxAtomicSub_inline vxAtomicSub
#define vxAtomic32Sub_inline vxAtomic32Sub
#define vxAtomicInc_inline vxAtomicInc
#define vxAtomic32Inc_inline vxAtomic32Inc
#define vxAtomicDec_inline vxAtomicDec
#define vxAtomic32Dec_inline vxAtomic32Dec
#define vxAtomicGet_inline vxAtomicGet
#define vxAtomic32Get_inline vxAtomic32Get
#define vxAtomicSet_inline vxAtomicSet
#define vxAtomic32Set_inline vxAtomic32Set
#define vxAtomicClear_inline vxAtomicClear
#define vxAtomic32Clear_inline vxAtomic32Clear
#endif /* _VX_TOOL_FAMILY */
#endif /* _ASMLANGUAGE */
#ifdef __cplusplus
}
#endif
#endif /* __INCvxAtomicArchLibh */