csutil/threading/atomicops_gcc_arm.h
00001 /* 00002 Copyright (C) 2010 by Stefano Angeleri 00003 2006 by Marten Svanfeldt 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 //NOTE: This could be a big problem with static linking but 00035 // I couldn't find a better way to implement it. 00036 // (Each plugin will have his copy making the lock useless) 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__
Generated for Crystal Space 2.0 by doxygen 1.6.1