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