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