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