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 58namespace android { 59 60#define INITIAL_STRONG_VALUE (1<<28) 61 62// --------------------------------------------------------------------------- 63 64class RefBase::weakref_impl : public RefBase::weakref_type 65{ 66public: 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 215private: 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 322void 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 341void 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 359void 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 381int32_t RefBase::getStrongCount() const 382{ 383 return mRefs->mStrong; 384} 385 386RefBase* RefBase::weakref_type::refBase() const 387{ 388 return static_cast<const weakref_impl*>(this)->mBase; 389} 390 391void 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 400void 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 432bool 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 536bool 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 557int32_t RefBase::weakref_type::getWeakCount() const 558{ 559 return static_cast<const weakref_impl*>(this)->mWeak; 560} 561 562void RefBase::weakref_type::printRefs() const 563{ 564 static_cast<const weakref_impl*>(this)->printRefs(); 565} 566 567void RefBase::weakref_type::trackMe(bool enable, bool retain) 568{ 569 static_cast<weakref_impl*>(this)->trackMe(enable, retain); 570} 571 572RefBase::weakref_type* RefBase::createWeak(const void* id) const 573{ 574 mRefs->incWeak(id); 575 return mRefs; 576} 577 578RefBase::weakref_type* RefBase::getWeakRefs() const 579{ 580 return mRefs; 581} 582 583RefBase::RefBase() 584 : mRefs(new weakref_impl(this)) 585{ 586} 587 588RefBase::~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 609void RefBase::extendObjectLifetime(int32_t mode) 610{ 611 android_atomic_or(mode, &mRefs->mFlags); 612} 613 614void RefBase::onFirstRef() 615{ 616} 617 618void RefBase::onLastStrongRef(const void* /*id*/) 619{ 620} 621 622bool RefBase::onIncStrongAttempted(uint32_t flags, const void* /*id*/) 623{ 624 return (flags&FIRST_INC_STRONG) ? true : false; 625} 626 627void RefBase::onLastWeakRef(const void* /*id*/) 628{ 629} 630 631// --------------------------------------------------------------------------- 632 633#if DEBUG_REFS 634void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) { 635 for (size_t i=0 ; i<n ; i++) { 636 renamer(i); 637 } 638} 639#else 640void RefBase::renameRefs(size_t /*n*/, const ReferenceRenamer& /*renamer*/) { } 641#endif 642 643void 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 650void 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