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