fix compile error for i386-optimized refcounting,
[enigma2.git] / lib / base / object.h
index 38a6dd359693470b5d62c161fc1690f6a9430e13..1723a885d994c9188815a58d2207590b7af38daf 100644 (file)
@@ -2,14 +2,12 @@
 #define __base_object_h
 
 #include <assert.h>
+#include <lib/base/smartptr.h>
+#include <lib/base/elock.h>
 
-// #define OBJECT_DEBUG
+//#define OBJECT_DEBUG
 
-#include <lib/base/smartptr.h>
-#ifdef OBJECT_DEBUG
 #include <lib/base/eerror.h>
-#endif
-#include <lib/base/elock.h>
 
 typedef int RESULT;
 
@@ -25,21 +23,50 @@ public:
        virtual void Release()=0;
 };
 
-class oRefCount
-{
-       int ref;
-public:
-       oRefCount(): ref(0) { }
-       operator int&() { return ref; }
-       ~oRefCount() { 
-#ifdef OBJECT_DEBUG
-               if (ref) eDebug("OBJECT_DEBUG FATAL: %p has %d references!", this, ref); else eDebug("OBJECT_DEBUG refcount ok! (%p)", this); 
-#endif
-       }
-};
-
 #ifndef SWIG
-       #if defined(__mips__)
+       struct oRefCount
+       {
+               volatile int count;
+               oRefCount(): count(0) { }
+               operator volatile int&() { return count; }
+               ~oRefCount()
+               { 
+       #ifdef OBJECT_DEBUG
+                       if (count)
+                               eDebug("OBJECT_DEBUG FATAL: %p has %d references!", this, count);
+                       else
+                               eDebug("OBJECT_DEBUG refcount ok! (%p)", this); 
+       #endif
+               }
+       };
+
+       #if defined(OBJECT_DEBUG)
+               extern int object_total_remaining;
+               #define DECLARE_REF(x)                  \
+                       private:oRefCount ref;  \
+                                       eSingleLock ref_lock; \
+                       public: void AddRef();          \
+                                       void Release();
+               #define DEFINE_REF(c) \
+                       void c::AddRef() \
+                       { \
+                               eSingleLocker l(ref_lock); \
+                               ++object_total_remaining; \
+                               ++ref; \
+                               eDebug("OBJECT_DEBUG " #c "+%p now %d", this, (int)ref); \
+                       } \
+                       void c::Release() \
+                       { \
+                               { \
+                                       eSingleLocker l(ref_lock); \
+                                       --object_total_remaining; \
+                                       --ref; \
+                                       eDebug("OBJECT_DEBUG " #c "-%p now %d", this, (int)ref); \
+                               } \
+                               if (!ref) \
+                                       delete this; \
+                       }
+       #elif defined(__mips__)
                #define DECLARE_REF(x)                  \
                        private: oRefCount ref;         \
                        public: void AddRef();          \
@@ -49,37 +76,37 @@ public:
                        { \
                                unsigned long temp; \
                                __asm__ __volatile__( \
-                               "               .set    mips3           \n" \
-                               "1:             ll              %0, %1          \n" \
-                               "               .set    mips0           \n" \
-                               "               addu    %0, 1           \n" \
-                               "               .set    mips3           \n" \
-                               "               sc              %0, %1          \n" \
-                               "               .set    mips0           \n" \
-                               "               beqz    %0, 1b          \n" \
-                               : "=&r" (temp), "=m" ((int)ref) \
-                               : "m" ((int)ref) \
-                               : "memory"); \
+                               "               .set    mips3                                                                                   \n" \
+                               "1:             ll              %0, %1  # load counter                                                  \n" \
+                               "               .set    mips0                                                                                   \n" \
+                               "               addu    %0, 1   # increment                                                             \n" \
+                               "               .set    mips3                                                                                   \n" \
+                               "               sc              %0, %1  # try to store, checking for atomicity  \n" \
+                               "               .set    mips0                                                                                   \n" \
+                               "               beqz    %0, 1b  # if not atomic (0), try again                  \n" \
+                               : "=&r" (temp), "=m" (ref.count) \
+                               : "m" (ref.count) \
+                               : ); \
                        } \
                        void c::Release() \
                        { \
                                unsigned long temp; \
                                __asm__ __volatile__( \
-                               "               .set    mips3           \n" \
-                               "1:             ll              %0, %1          \n" \
-                               "               .set    mips0           \n" \
-                               "               subu    %0, 1           \n" \
-                               "               .set    mips3           \n" \
-                               "               sc              %0, %1          \n" \
-                               "               .set    mips0           \n" \
-                               "               beqz    %0, 1b          \n" \
-                               : "=&r" (temp), "=m" ((int)ref) \
-                               : "m" ((int)ref) \
-                               : "memory"); \
+                               "               .set    mips3                           \n" \
+                               "1:             ll              %0, %1                          \n" \
+                               "               .set    mips0                           \n" \
+                               "               subu    %0, 1   # decrement     \n" \
+                               "               .set    mips3                           \n" \
+                               "               sc              %0, %1                          \n" \
+                               "               .set    mips0                           \n" \
+                               "               beqz    %0, 1b                          \n" \
+                               : "=&r" (temp), "=m" (ref.count) \
+                               : "m" (ref.count) \
+                               : ); \
                                if (!ref) \
                                        delete this; \
                        }
-       #elif defined(__ppc__)
+       #elif defined(__ppc__) || defined(__powerpc__)
                #define DECLARE_REF(x)                  \
                        private: oRefCount ref;         \
                        public: void AddRef();          \
@@ -91,11 +118,11 @@ public:
                                __asm__ __volatile__( \
                                "1:             lwarx   %0, 0, %3       \n" \
                                "               add             %0, %2, %0      \n" \
-                               "               dcbt    0, %3           \n" \
+                               "               dcbt    0, %3           # workaround for PPC405CR Errata\n" \
                                "               stwcx.  %0, 0, %3       \n" \
                                "               bne-    1b                      \n" \
-                               : "=&r" (temp), "=m" ((int)ref) \
-                               : "r" (1), "r" (&((int)ref)), "m" ((int)ref) \
+                               : "=&r" (temp), "=m" (ref.count) \
+                               : "r" (1), "r" (&ref.count), "m" (ref.count) \
                                : "cc"); \
                        } \
                        void c::Release() \
@@ -104,72 +131,68 @@ public:
                                __asm__ __volatile__( \
                                "1:             lwarx   %0, 0, %3       \n" \
                                "               subf    %0, %2, %0      \n" \
-                               "               dcbt    0, %3           \n" \
+                               "               dcbt    0, %3           # workaround for PPC405CR Errata\n" \
                                "               stwcx.  %0, 0, %3       \n" \
                                "               bne-    1b                      \n" \
-                               : "=&r" (temp), "=m" ((int)ref) \
-                               : "r" (1), "r" (&((int)ref)), "m" ((int)ref) \
+                               : "=&r" (temp), "=m" (ref.count) \
+                               : "r" (1), "r" (&ref.count), "m" (ref.count) \
                                : "cc"); \
                                if (!ref) \
                                        delete this; \
                        }
+       #elif defined(__i386__) || defined(__x86_64__)
+               #define DECLARE_REF(x)                  \
+                       private: oRefCount ref;         \
+                       public: void AddRef();          \
+                                       void Release();
+               #define DEFINE_REF(c) \
+                       void c::AddRef() \
+                       { \
+                               __asm__ __volatile__( \
+                               "               lock ; incl     %0      \n" \
+                               : "=m" (ref.count) \
+                               : "m" (ref.count)); \
+                       } \
+                       void c::Release() \
+                       { \
+                               __asm__ __volatile__( \
+                               "               lock ; decl     %0      \n" \
+                               : "=m" (ref.count) \
+                               : "m" (ref.count)); \
+                               if (!ref) \
+                                       delete this; \
+                       }
        #else
+               #warning use non optimized implementation of refcounting.
                #define DECLARE_REF(x)                  \
                        private:oRefCount ref;  \
                                        eSingleLock ref_lock; \
                        public: void AddRef();          \
                                        void Release();
-               #ifdef OBJECT_DEBUG
-                       extern int object_total_remaining;
-                       #define DEFINE_REF(c) \
-                               void c::AddRef() \
-                               { \
-                                       eSingleLocker l(ref_lock); \
-                                       ++object_total_remaining; \
-                                       ++ref; \
-                                       eDebug("OBJECT_DEBUG " #c "+%p now %d", this, (int)ref); \
-                               } \
-                               void c::Release() \
-                               { \
-                                       { \
-                                               eSingleLocker l(ref_lock); \
-                                               --object_total_remaining; \
-                                               --ref; \
-                                               eDebug("OBJECT_DEBUG " #c "-%p now %d", this, ref); \
-                                       } \
-                                       if (!ref) \
-                                               delete this; \
-                               }
-                               #error fix locking for debug
-               #else
-                       #define DEFINE_REF(c) \
-                               void c::AddRef() \
+               #define DEFINE_REF(c) \
+                       void c::AddRef() \
+                       { \
+                               eSingleLocker l(ref_lock); \
+                               ++ref; \
+                       } \
+                       void c::Release() \
+                       { \
                                { \
                                        eSingleLocker l(ref_lock); \
-                                       ++ref; \
+                                       --ref; \
                                } \
-                               void c::Release() \
-                               { \
-                                       { \
-                                               eSingleLocker l(ref_lock); \
-                                               --ref; \
-                                       } \
-                                       if (!ref) \
-                                               delete this; \
-                               }
-               #endif
+                               if (!ref) \
+                                       delete this; \
+                       }
        #endif
-#else
+#else  // SWIG
        #define DECLARE_REF(x) \
                private: \
                        void AddRef(); \
                        void Release();
-#endif
-
-#ifdef SWIG
-class Object
-{
-};
-#endif
+       class Object
+       {
+       };
+#endif  // SWIG
 
-#endif
+#endif  // __base_object_h