Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2005 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "RefBase"
     18 
     19 #include <utils/RefBase.h>
     20 
     21 #include <utils/Atomic.h>
     22 #include <utils/CallStack.h>
     23 #include <utils/Log.h>
     24 #include <utils/threads.h>
     25 #include <utils/TextOutput.h>
     26 
     27 #include <stdlib.h>
     28 #include <stdio.h>
     29 #include <typeinfo>
     30 #include <sys/types.h>
     31 #include <sys/stat.h>
     32 #include <fcntl.h>
     33 #include <unistd.h>
     34 
     35 // compile with refcounting debugging enabled
     36 #define DEBUG_REFS                      0
     37 #define DEBUG_REFS_FATAL_SANITY_CHECKS  0
     38 #define DEBUG_REFS_ENABLED_BY_DEFAULT   1
     39 #define DEBUG_REFS_CALLSTACK_ENABLED    1
     40 
     41 // log all reference counting operations
     42 #define PRINT_REFS                      0
     43 
     44 // ---------------------------------------------------------------------------
     45 
     46 namespace android {
     47 
     48 #define INITIAL_STRONG_VALUE (1<<28)
     49 
     50 // ---------------------------------------------------------------------------
     51 
     52 class RefBase::weakref_impl : public RefBase::weakref_type
     53 {
     54 public:
     55     volatile int32_t    mStrong;
     56     volatile int32_t    mWeak;
     57     RefBase* const      mBase;
     58     volatile int32_t    mFlags;
     59 
     60 #if !DEBUG_REFS
     61 
     62     weakref_impl(RefBase* base)
     63         : mStrong(INITIAL_STRONG_VALUE)
     64         , mWeak(0)
     65         , mBase(base)
     66         , mFlags(0)
     67     {
     68     }
     69 
     70     void addStrongRef(const void* /*id*/) { }
     71     void removeStrongRef(const void* /*id*/) { }
     72     void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
     73     void addWeakRef(const void* /*id*/) { }
     74     void removeWeakRef(const void* /*id*/) { }
     75     void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
     76     void printRefs() const { }
     77     void trackMe(bool, bool) { }
     78 
     79 #else
     80 
     81     weakref_impl(RefBase* base)
     82         : mStrong(INITIAL_STRONG_VALUE)
     83         , mWeak(0)
     84         , mBase(base)
     85         , mFlags(0)
     86         , mStrongRefs(NULL)
     87         , mWeakRefs(NULL)
     88         , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
     89         , mRetain(false)
     90     {
     91     }
     92 
     93     ~weakref_impl()
     94     {
     95         bool dumpStack = false;
     96         if (!mRetain && mStrongRefs != NULL) {
     97             dumpStack = true;
     98 #if DEBUG_REFS_FATAL_SANITY_CHECKS
     99             LOG_ALWAYS_FATAL("Strong references remain!");
    100 #else
    101             LOGE("Strong references remain:");
    102 #endif
    103             ref_entry* refs = mStrongRefs;
    104             while (refs) {
    105                 char inc = refs->ref >= 0 ? '+' : '-';
    106                 LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
    107 #if DEBUG_REFS_CALLSTACK_ENABLED
    108                 refs->stack.dump();
    109 #endif
    110                 refs = refs->next;
    111             }
    112         }
    113 
    114         if (!mRetain && mWeakRefs != NULL) {
    115             dumpStack = true;
    116 #if DEBUG_REFS_FATAL_SANITY_CHECKS
    117             LOG_ALWAYS_FATAL("Weak references remain:");
    118 #else
    119             LOGE("Weak references remain!");
    120 #endif
    121             ref_entry* refs = mWeakRefs;
    122             while (refs) {
    123                 char inc = refs->ref >= 0 ? '+' : '-';
    124                 LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
    125 #if DEBUG_REFS_CALLSTACK_ENABLED
    126                 refs->stack.dump();
    127 #endif
    128                 refs = refs->next;
    129             }
    130         }
    131         if (dumpStack) {
    132             LOGE("above errors at:");
    133             CallStack stack;
    134             stack.update();
    135             stack.dump();
    136         }
    137     }
    138 
    139     void addStrongRef(const void* id) {
    140         //LOGD_IF(mTrackEnabled,
    141         //        "addStrongRef: RefBase=%p, id=%p", mBase, id);
    142         addRef(&mStrongRefs, id, mStrong);
    143     }
    144 
    145     void removeStrongRef(const void* id) {
    146         //LOGD_IF(mTrackEnabled,
    147         //        "removeStrongRef: RefBase=%p, id=%p", mBase, id);
    148         if (!mRetain) {
    149             removeRef(&mStrongRefs, id);
    150         } else {
    151             addRef(&mStrongRefs, id, -mStrong);
    152         }
    153     }
    154 
    155     void renameStrongRefId(const void* old_id, const void* new_id) {
    156         //LOGD_IF(mTrackEnabled,
    157         //        "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
    158         //        mBase, old_id, new_id);
    159         renameRefsId(mStrongRefs, old_id, new_id);
    160     }
    161 
    162     void addWeakRef(const void* id) {
    163         addRef(&mWeakRefs, id, mWeak);
    164     }
    165 
    166     void removeWeakRef(const void* id) {
    167         if (!mRetain) {
    168             removeRef(&mWeakRefs, id);
    169         } else {
    170             addRef(&mWeakRefs, id, -mWeak);
    171         }
    172     }
    173 
    174     void renameWeakRefId(const void* old_id, const void* new_id) {
    175         renameRefsId(mWeakRefs, old_id, new_id);
    176     }
    177 
    178     void trackMe(bool track, bool retain)
    179     {
    180         mTrackEnabled = track;
    181         mRetain = retain;
    182     }
    183 
    184     void printRefs() const
    185     {
    186         String8 text;
    187 
    188         {
    189             Mutex::Autolock _l(mMutex);
    190             char buf[128];
    191             sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
    192             text.append(buf);
    193             printRefsLocked(&text, mStrongRefs);
    194             sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
    195             text.append(buf);
    196             printRefsLocked(&text, mWeakRefs);
    197         }
    198 
    199         {
    200             char name[100];
    201             snprintf(name, 100, "/data/%p.stack", this);
    202             int rc = open(name, O_RDWR | O_CREAT | O_APPEND);
    203             if (rc >= 0) {
    204                 write(rc, text.string(), text.length());
    205                 close(rc);
    206                 LOGD("STACK TRACE for %p saved in %s", this, name);
    207             }
    208             else LOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
    209                       name, strerror(errno));
    210         }
    211     }
    212 
    213 private:
    214     struct ref_entry
    215     {
    216         ref_entry* next;
    217         const void* id;
    218 #if DEBUG_REFS_CALLSTACK_ENABLED
    219         CallStack stack;
    220 #endif
    221         int32_t ref;
    222     };
    223 
    224     void addRef(ref_entry** refs, const void* id, int32_t mRef)
    225     {
    226         if (mTrackEnabled) {
    227             AutoMutex _l(mMutex);
    228 
    229             ref_entry* ref = new ref_entry;
    230             // Reference count at the time of the snapshot, but before the
    231             // update.  Positive value means we increment, negative--we
    232             // decrement the reference count.
    233             ref->ref = mRef;
    234             ref->id = id;
    235 #if DEBUG_REFS_CALLSTACK_ENABLED
    236             ref->stack.update(2);
    237 #endif
    238             ref->next = *refs;
    239             *refs = ref;
    240         }
    241     }
    242 
    243     void removeRef(ref_entry** refs, const void* id)
    244     {
    245         if (mTrackEnabled) {
    246             AutoMutex _l(mMutex);
    247 
    248             ref_entry* const head = *refs;
    249             ref_entry* ref = head;
    250             while (ref != NULL) {
    251                 if (ref->id == id) {
    252                     *refs = ref->next;
    253                     delete ref;
    254                     return;
    255                 }
    256                 refs = &ref->next;
    257                 ref = *refs;
    258             }
    259 
    260 #if DEBUG_REFS_FATAL_SANITY_CHECKS
    261             LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p"
    262                     "(weakref_type %p) that doesn't exist!",
    263                     id, mBase, this);
    264 #endif
    265 
    266             LOGE("RefBase: removing id %p on RefBase %p"
    267                     "(weakref_type %p) that doesn't exist!",
    268                     id, mBase, this);
    269 
    270             ref = head;
    271             while (ref) {
    272                 char inc = ref->ref >= 0 ? '+' : '-';
    273                 LOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
    274                 ref = ref->next;
    275             }
    276 
    277             CallStack stack;
    278             stack.update();
    279             stack.dump();
    280         }
    281     }
    282 
    283     void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
    284     {
    285         if (mTrackEnabled) {
    286             AutoMutex _l(mMutex);
    287             ref_entry* ref = r;
    288             while (ref != NULL) {
    289                 if (ref->id == old_id) {
    290                     ref->id = new_id;
    291                 }
    292                 ref = ref->next;
    293             }
    294         }
    295     }
    296 
    297     void printRefsLocked(String8* out, const ref_entry* refs) const
    298     {
    299         char buf[128];
    300         while (refs) {
    301             char inc = refs->ref >= 0 ? '+' : '-';
    302             sprintf(buf, "\t%c ID %p (ref %d):\n",
    303                     inc, refs->id, refs->ref);
    304             out->append(buf);
    305 #if DEBUG_REFS_CALLSTACK_ENABLED
    306             out->append(refs->stack.toString("\t\t"));
    307 #else
    308             out->append("\t\t(call stacks disabled)");
    309 #endif
    310             refs = refs->next;
    311         }
    312     }
    313 
    314     mutable Mutex mMutex;
    315     ref_entry* mStrongRefs;
    316     ref_entry* mWeakRefs;
    317 
    318     bool mTrackEnabled;
    319     // Collect stack traces on addref and removeref, instead of deleting the stack references
    320     // on removeref that match the address ones.
    321     bool mRetain;
    322 
    323 #endif
    324 };
    325 
    326 // ---------------------------------------------------------------------------
    327 
    328 void RefBase::incStrong(const void* id) const
    329 {
    330     weakref_impl* const refs = mRefs;
    331     refs->incWeak(id);
    332 
    333     refs->addStrongRef(id);
    334     const int32_t c = android_atomic_inc(&refs->mStrong);
    335     LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
    336 #if PRINT_REFS
    337     LOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
    338 #endif
    339     if (c != INITIAL_STRONG_VALUE)  {
    340         return;
    341     }
    342 
    343     android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    344     refs->mBase->onFirstRef();
    345 }
    346 
    347 void RefBase::decStrong(const void* id) const
    348 {
    349     weakref_impl* const refs = mRefs;
    350     refs->removeStrongRef(id);
    351     const int32_t c = android_atomic_dec(&refs->mStrong);
    352 #if PRINT_REFS
    353     LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
    354 #endif
    355     LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
    356     if (c == 1) {
    357         refs->mBase->onLastStrongRef(id);
    358         if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
    359             delete this;
    360         }
    361     }
    362     refs->decWeak(id);
    363 }
    364 
    365 void RefBase::forceIncStrong(const void* id) const
    366 {
    367     weakref_impl* const refs = mRefs;
    368     refs->incWeak(id);
    369 
    370     refs->addStrongRef(id);
    371     const int32_t c = android_atomic_inc(&refs->mStrong);
    372     LOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
    373                refs);
    374 #if PRINT_REFS
    375     LOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
    376 #endif
    377 
    378     switch (c) {
    379     case INITIAL_STRONG_VALUE:
    380         android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    381         // fall through...
    382     case 0:
    383         refs->mBase->onFirstRef();
    384     }
    385 }
    386 
    387 int32_t RefBase::getStrongCount() const
    388 {
    389     return mRefs->mStrong;
    390 }
    391 
    392 RefBase* RefBase::weakref_type::refBase() const
    393 {
    394     return static_cast<const weakref_impl*>(this)->mBase;
    395 }
    396 
    397 void RefBase::weakref_type::incWeak(const void* id)
    398 {
    399     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    400     impl->addWeakRef(id);
    401     const int32_t c = android_atomic_inc(&impl->mWeak);
    402     LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
    403 }
    404 
    405 
    406 void RefBase::weakref_type::decWeak(const void* id)
    407 {
    408     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    409     impl->removeWeakRef(id);
    410     const int32_t c = android_atomic_dec(&impl->mWeak);
    411     LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    412     if (c != 1) return;
    413 
    414     if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
    415         // This is the regular lifetime case. The object is destroyed
    416         // when the last strong reference goes away. Since weakref_impl
    417         // outlive the object, it is not destroyed in the dtor, and
    418         // we'll have to do it here.
    419         if (impl->mStrong == INITIAL_STRONG_VALUE) {
    420             // Special case: we never had a strong reference, so we need to
    421             // destroy the object now.
    422             delete impl->mBase;
    423         } else {
    424             // LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
    425             delete impl;
    426         }
    427     } else {
    428         // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
    429         impl->mBase->onLastWeakRef(id);
    430         if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
    431             // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
    432             // is gone, we can destroy the object.
    433             delete impl->mBase;
    434         }
    435     }
    436 }
    437 
    438 bool RefBase::weakref_type::attemptIncStrong(const void* id)
    439 {
    440     incWeak(id);
    441 
    442     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    443 
    444     int32_t curCount = impl->mStrong;
    445     LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
    446                this);
    447     while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
    448         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
    449             break;
    450         }
    451         curCount = impl->mStrong;
    452     }
    453 
    454     if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
    455         bool allow;
    456         if (curCount == INITIAL_STRONG_VALUE) {
    457             // Attempting to acquire first strong reference...  this is allowed
    458             // if the object does NOT have a longer lifetime (meaning the
    459             // implementation doesn't need to see this), or if the implementation
    460             // allows it to happen.
    461             allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
    462                   || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
    463         } else {
    464             // Attempting to revive the object...  this is allowed
    465             // if the object DOES have a longer lifetime (so we can safely
    466             // call the object with only a weak ref) and the implementation
    467             // allows it to happen.
    468             allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
    469                   && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
    470         }
    471         if (!allow) {
    472             decWeak(id);
    473             return false;
    474         }
    475         curCount = android_atomic_inc(&impl->mStrong);
    476 
    477         // If the strong reference count has already been incremented by
    478         // someone else, the implementor of onIncStrongAttempted() is holding
    479         // an unneeded reference.  So call onLastStrongRef() here to remove it.
    480         // (No, this is not pretty.)  Note that we MUST NOT do this if we
    481         // are in fact acquiring the first reference.
    482         if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
    483             impl->mBase->onLastStrongRef(id);
    484         }
    485     }
    486 
    487     impl->addStrongRef(id);
    488 
    489 #if PRINT_REFS
    490     LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
    491 #endif
    492 
    493     if (curCount == INITIAL_STRONG_VALUE) {
    494         android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
    495         impl->mBase->onFirstRef();
    496     }
    497 
    498     return true;
    499 }
    500 
    501 bool RefBase::weakref_type::attemptIncWeak(const void* id)
    502 {
    503     weakref_impl* const impl = static_cast<weakref_impl*>(this);
    504 
    505     int32_t curCount = impl->mWeak;
    506     LOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
    507                this);
    508     while (curCount > 0) {
    509         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
    510             break;
    511         }
    512         curCount = impl->mWeak;
    513     }
    514 
    515     if (curCount > 0) {
    516         impl->addWeakRef(id);
    517     }
    518 
    519     return curCount > 0;
    520 }
    521 
    522 int32_t RefBase::weakref_type::getWeakCount() const
    523 {
    524     return static_cast<const weakref_impl*>(this)->mWeak;
    525 }
    526 
    527 void RefBase::weakref_type::printRefs() const
    528 {
    529     static_cast<const weakref_impl*>(this)->printRefs();
    530 }
    531 
    532 void RefBase::weakref_type::trackMe(bool enable, bool retain)
    533 {
    534     static_cast<weakref_impl*>(this)->trackMe(enable, retain);
    535 }
    536 
    537 RefBase::weakref_type* RefBase::createWeak(const void* id) const
    538 {
    539     mRefs->incWeak(id);
    540     return mRefs;
    541 }
    542 
    543 RefBase::weakref_type* RefBase::getWeakRefs() const
    544 {
    545     return mRefs;
    546 }
    547 
    548 RefBase::RefBase()
    549     : mRefs(new weakref_impl(this))
    550 {
    551 }
    552 
    553 RefBase::~RefBase()
    554 {
    555     if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
    556         // we never acquired a strong (and/or weak) reference on this object.
    557         delete mRefs;
    558     } else {
    559         // life-time of this object is extended to WEAK or FOREVER, in
    560         // which case weakref_impl doesn't out-live the object and we
    561         // can free it now.
    562         if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
    563             // It's possible that the weak count is not 0 if the object
    564             // re-acquired a weak reference in its destructor
    565             if (mRefs->mWeak == 0) {
    566                 delete mRefs;
    567             }
    568         }
    569     }
    570     // for debugging purposes, clear this.
    571     const_cast<weakref_impl*&>(mRefs) = NULL;
    572 }
    573 
    574 void RefBase::extendObjectLifetime(int32_t mode)
    575 {
    576     android_atomic_or(mode, &mRefs->mFlags);
    577 }
    578 
    579 void RefBase::onFirstRef()
    580 {
    581 }
    582 
    583 void RefBase::onLastStrongRef(const void* /*id*/)
    584 {
    585 }
    586 
    587 bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
    588 {
    589     return (flags&FIRST_INC_STRONG) ? true : false;
    590 }
    591 
    592 void RefBase::onLastWeakRef(const void* /*id*/)
    593 {
    594 }
    595 
    596 // ---------------------------------------------------------------------------
    597 
    598 void RefBase::moveReferences(void* dst, void const* src, size_t n,
    599         const ReferenceConverterBase& caster)
    600 {
    601 #if DEBUG_REFS
    602     const size_t itemSize = caster.getReferenceTypeSize();
    603     for (size_t i=0 ; i<n ; i++) {
    604         void*       d = reinterpret_cast<void      *>(intptr_t(dst) + i*itemSize);
    605         void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize);
    606         RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d)));
    607         ref->mRefs->renameStrongRefId(s, d);
    608         ref->mRefs->renameWeakRefId(s, d);
    609     }
    610 #endif
    611 }
    612 
    613 // ---------------------------------------------------------------------------
    614 
    615 TextOutput& printStrongPointer(TextOutput& to, const void* val)
    616 {
    617     to << "sp<>(" << val << ")";
    618     return to;
    619 }
    620 
    621 TextOutput& printWeakPointer(TextOutput& to, const void* val)
    622 {
    623     to << "wp<>(" << val << ")";
    624     return to;
    625 }
    626 
    627 
    628 }; // namespace android
    629