atomic.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005 Palmsource, Inc.
00003  * 
00004  * This software is licensed as described in the file LICENSE, which
00005  * you should have received as part of this distribution. The terms
00006  * are also available at http://www.openbinder.org/license.html.
00007  * 
00008  * This software consists of voluntary contributions made by many
00009  * individuals. For the exact contribution history, see the revision
00010  * history and logs, available at http://www.openbinder.org
00011  */
00012 
00013 #ifndef _SUPPORT_ATOMIC_H
00014 #define _SUPPORT_ATOMIC_H
00015 
00021 #include <support/SupportDefs.h>
00022 
00023 #include <SysThread.h>
00024 
00025 #ifdef __cplusplus
00026 
00028 
00029 struct SAtomicInt32
00030 {
00031 public:
00032     inline  int32_t             Value() const;
00033     inline  void                SetTo(int32_t newVal);
00034 
00035     inline  int32_t             Add(int32_t amount);
00036     inline  bool                Swap(int32_t oldVal, int32_t newVal);
00037 
00038     inline  uint32_t            Or(uint32_t bits);
00039     inline  uint32_t            And(uint32_t bits);
00040 
00041 private:
00042     volatile int32_t            m_value;
00043 };
00044 
00045 extern "C" {
00046 
00047 #endif  // __cplusplus
00048 
00049 /* not in the SDK, but exported for PDK use */
00050 uint32_t SysAtomicCompareAndSwap64(uint64_t volatile *ioOperandP, uint64_t iOldValue, uint64_t iNewValue);
00051 
00052 /*
00053  * Lightweight locking (implemented in Locker.cpp)
00054  */
00055 extern void _IMPEXP_SUPPORT SysCriticalSectionEnter(SysCriticalSectionType *iCS);
00056 extern void _IMPEXP_SUPPORT SysCriticalSectionExit(SysCriticalSectionType *iCS);
00057 
00058 /*
00059  * Lightweight condition variables (also in Locker.cpp)
00060  */
00061 extern void _IMPEXP_SUPPORT SysConditionVariableWait(SysConditionVariableType *iCV, SysCriticalSectionType *iOptionalCS);
00062 extern void _IMPEXP_SUPPORT SysConditionVariableOpen(SysConditionVariableType *iCV);
00063 extern void _IMPEXP_SUPPORT SysConditionVariableClose(SysConditionVariableType *iCV);
00064 extern void _IMPEXP_SUPPORT SysConditionVariableBroadcast(SysConditionVariableType *iCV);
00065 
00066 extern int32_t  _IMPEXP_SUPPORT atomic_add(volatile int32_t *value, int32_t addvalue);
00067 extern int32_t  _IMPEXP_SUPPORT atomic_and(volatile int32_t *value, int32_t andvalue);
00068 extern int32_t  _IMPEXP_SUPPORT atomic_or(volatile int32_t *value, int32_t orvalue);
00069 extern int32_t  _IMPEXP_SUPPORT compare_and_swap32(volatile int32_t *location, int32_t oldValue, int32_t newValue);
00070 extern int32_t  _IMPEXP_SUPPORT compare_and_swap64(volatile int64_t *location, int64_t oldValue, int64_t newValue);
00071 
00072 #if TARGET_HOST == TARGET_HOST_WIN32
00073 
00074 
00075 // Synonyms from PalmOS.
00076 inline int32_t SysAtomicAdd32(int32_t volatile* ioOperandP, int32_t iAddend)
00077     { return (int32_t)atomic_add((int32_t volatile*)ioOperandP, (int32_t)iAddend); }
00078 inline uint32_t SysAtomicAnd32(uint32_t volatile* ioOperandP, uint32_t iValue)
00079     { return (uint32_t)atomic_and((int32_t volatile*)ioOperandP, (int32_t)iValue); }
00080 inline uint32_t SysAtomicOr32(uint32_t volatile* ioOperandP, uint32_t iValue)
00081     { return (uint32_t)atomic_or((int32_t volatile*)ioOperandP, (int32_t)iValue); }
00082 inline uint32_t SysAtomicCompareAndSwap32(uint32_t volatile* ioOperandP, uint32_t iOldValue, uint32_t iNewValue)
00083     { return (uint32_t)!compare_and_swap32((int32_t volatile*)ioOperandP, (int32_t)iOldValue, (int32_t)iNewValue); }
00084 inline uint32_t SysAtomicCompareAndSwap64(uint64_t volatile* ioOperandP, uint64_t iOldValue, uint64_t iNewValue)
00085     { return (uint32_t)!compare_and_swap64((int64_t volatile*)ioOperandP, (int64_t)iOldValue, (int64_t)iNewValue); }
00086 
00087 #endif  // #if TARGET_HOST == TARGET_HOST_WIN32
00088 
00090 
00095 INLINE_FNC int cmpxchg32(volatile int32_t *atom, int32_t *value, int32_t newValue)
00096 {
00097     if (SysAtomicCompareAndSwap32((volatile uint32_t*)atom, *value, newValue)) {
00098         // Failed.
00099         *value = *atom;
00100         return FALSE;
00101     }
00102 
00103     return TRUE;
00104 }
00105 
00107 
00112 INLINE_FNC int cmpxchg64(volatile int64_t *atom, int64_t *value, int64_t newValue)
00113 {
00114     int32_t success = compare_and_swap64(atom, *value, newValue);
00115     if (!success)
00116         *value = *atom;
00117 
00118     return success ? TRUE : FALSE;
00119 }
00120 
00121 /*-------------------------------------------------------------*/
00122 /*---- No user serviceable parts after this -------------------*/
00123 
00124 #ifdef __cplusplus
00125 }
00126 
00127 inline int32_t SAtomicInt32::Value() const
00128 {
00129     return m_value;
00130 }
00131 
00132 inline void SAtomicInt32::SetTo(int32_t newVal)
00133 {
00134     m_value = newVal;
00135 }
00136 
00137 inline int32_t SAtomicInt32::Add(int32_t amount)
00138 {
00139     return SysAtomicAdd32(&m_value, amount);
00140 }
00141 
00142 inline bool SAtomicInt32::Swap(int32_t oldVal, int32_t newVal)
00143 {
00144     return SysAtomicCompareAndSwap32((volatile uint32_t*)&m_value, oldVal, newVal) == 0;
00145 }
00146 
00147 inline uint32_t SAtomicInt32::Or(uint32_t bits)
00148 {
00149     return SysAtomicOr32((volatile uint32_t*)&m_value, bits);
00150 }
00151 
00152 inline uint32_t SAtomicInt32::And(uint32_t bits)
00153 {
00154     return SysAtomicAnd32((volatile uint32_t*)&m_value, bits);
00155 }
00156 
00157 #endif  // __cplusplus
00158 
00159 #endif /* _SUPPORT_ATOMIC_H */