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