00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __CS_CSUTIL_ATOMICOPS_GCC_ARM_H__
00021 #define __CS_CSUTIL_ATOMICOPS_GCC_ARM_H__
00022
00023 #ifndef DOXYGEN_RUN
00024
00025 namespace CS
00026 {
00027 namespace Threading
00028 {
00029 class CS_CRYSTALSPACE_EXPORT AtomicOperationsArmGCC
00030 {
00031
00032 private:
00033
00034
00035
00036
00037 static char AtomicLock;
00038
00039 inline static char Swpb(volatile char *target, char value)
00040 {
00041 register char ret;
00042 asm volatile("swpb %0 , %2, [%3]"
00043 : "=&r"(ret), "=m" (*target)
00044 : "r"(value), "r"(target)
00045 : "cc", "memory");
00046 return ret;
00047 }
00048
00049 public:
00050
00051 inline static int32 Set (int32* target, int32 value)
00052 {
00053 while(Swpb(&AtomicLock, ~0) != 0);
00054 *target = value;
00055 Swpb(&AtomicLock, 0);
00056 return value;
00057 }
00058
00059 inline static void* Set (void** target, void* value)
00060 {
00061 return (void*)Set ((int32*)target, (int32)value);
00062 }
00063
00064 inline static int32 CompareAndSet (int32* target, int32 value,
00065 int32 comparand)
00066 {
00067
00068 while(Swpb(&AtomicLock, ~0) != 0);
00069 int32 oldvalue = *target;
00070 if(*target == comparand)
00071 *target = value;
00072 Swpb(&AtomicLock, 0);
00073 return oldvalue;
00074 }
00075
00076 inline static void* CompareAndSet (void** target, void* value,
00077 void* comparand)
00078 {
00079 return (void*)CompareAndSet ((int32*)target, (int32)value,
00080 (int32)comparand);
00081 }
00082
00083 inline static int32 Increment (int32* target, register int32 incr = 1)
00084 {
00085 while(Swpb(&AtomicLock, ~0) != 0);
00086 *target += incr;
00087 int32 ret = *target;
00088 Swpb(&AtomicLock, 0);
00089 return ret;
00090 }
00091
00092 inline static int32 Decrement (int32* target)
00093 {
00094 return (int32)Increment (target, -1);
00095 }
00096 };
00097 }
00098 }
00099
00100 #endif // DOXYGEN_RUN
00101
00102 #endif // __CS_CSUTIL_ATOMICOPS_GCC_ARM_H__