OSDN Git Service

Merge "Fix issue #4539687: At least one compatibility-mode app (Androminion)..."...
[android-x86/frameworks-base.git] / libs / utils / RefBase.cpp
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
46 namespace android {
47
48 #define INITIAL_STRONG_VALUE (1<<28)
49
50 // ---------------------------------------------------------------------------
51
52 class RefBase::weakref_impl : public RefBase::weakref_type
53 {
54 public:
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
214 private:
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
329 void 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
348 void RefBase::destroy() const {
349     delete this;
350 }
351
352 void RefBase::decStrong(const void* id) const
353 {
354     weakref_impl* const refs = mRefs;
355     refs->removeStrongRef(id);
356     const int32_t c = android_atomic_dec(&refs->mStrong);
357 #if PRINT_REFS
358     LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
359 #endif
360     LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
361     if (c == 1) {
362         const_cast<RefBase*>(this)->onLastStrongRef(id);
363         if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
364             destroy();
365         }
366     }
367     refs->decWeak(id);
368 }
369
370 void RefBase::forceIncStrong(const void* id) const
371 {
372     weakref_impl* const refs = mRefs;
373     refs->incWeak(id);
374     
375     refs->addStrongRef(id);
376     const int32_t c = android_atomic_inc(&refs->mStrong);
377     LOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
378                refs);
379 #if PRINT_REFS
380     LOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
381 #endif
382
383     switch (c) {
384     case INITIAL_STRONG_VALUE:
385         android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
386         // fall through...
387     case 0:
388         const_cast<RefBase*>(this)->onFirstRef();
389     }
390 }
391
392 int32_t RefBase::getStrongCount() const
393 {
394     return mRefs->mStrong;
395 }
396
397
398
399 RefBase* RefBase::weakref_type::refBase() const
400 {
401     return static_cast<const weakref_impl*>(this)->mBase;
402 }
403
404 void RefBase::weakref_type::incWeak(const void* id)
405 {
406     weakref_impl* const impl = static_cast<weakref_impl*>(this);
407     impl->addWeakRef(id);
408     const int32_t c = android_atomic_inc(&impl->mWeak);
409     LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
410 }
411
412 void RefBase::weakref_type::decWeak(const void* id)
413 {
414     weakref_impl* const impl = static_cast<weakref_impl*>(this);
415     impl->removeWeakRef(id);
416     const int32_t c = android_atomic_dec(&impl->mWeak);
417     LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
418     if (c != 1) return;
419     
420     if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
421         if (impl->mStrong == INITIAL_STRONG_VALUE)
422             if (impl->mBase)
423                 impl->mBase->destroy();
424         else {
425             // LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
426             delete impl;
427         }
428     } else {
429         impl->mBase->onLastWeakRef(id);
430         if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
431             if (impl->mBase)
432                 impl->mBase->destroy();
433         }
434     }
435 }
436
437 bool RefBase::weakref_type::attemptIncStrong(const void* id)
438 {
439     incWeak(id);
440     
441     weakref_impl* const impl = static_cast<weakref_impl*>(this);
442     
443     int32_t curCount = impl->mStrong;
444     LOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
445                this);
446     while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
447         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
448             break;
449         }
450         curCount = impl->mStrong;
451     }
452     
453     if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
454         bool allow;
455         if (curCount == INITIAL_STRONG_VALUE) {
456             // Attempting to acquire first strong reference...  this is allowed
457             // if the object does NOT have a longer lifetime (meaning the
458             // implementation doesn't need to see this), or if the implementation
459             // allows it to happen.
460             allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
461                   || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
462         } else {
463             // Attempting to revive the object...  this is allowed
464             // if the object DOES have a longer lifetime (so we can safely
465             // call the object with only a weak ref) and the implementation
466             // allows it to happen.
467             allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
468                   && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
469         }
470         if (!allow) {
471             decWeak(id);
472             return false;
473         }
474         curCount = android_atomic_inc(&impl->mStrong);
475
476         // If the strong reference count has already been incremented by
477         // someone else, the implementor of onIncStrongAttempted() is holding
478         // an unneeded reference.  So call onLastStrongRef() here to remove it.
479         // (No, this is not pretty.)  Note that we MUST NOT do this if we
480         // are in fact acquiring the first reference.
481         if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
482             impl->mBase->onLastStrongRef(id);
483         }
484     }
485     
486     impl->addStrongRef(id);
487
488 #if PRINT_REFS
489     LOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
490 #endif
491
492     if (curCount == INITIAL_STRONG_VALUE) {
493         android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
494         impl->mBase->onFirstRef();
495     }
496     
497     return true;
498 }
499
500 bool RefBase::weakref_type::attemptIncWeak(const void* id)
501 {
502     weakref_impl* const impl = static_cast<weakref_impl*>(this);
503
504     int32_t curCount = impl->mWeak;
505     LOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
506                this);
507     while (curCount > 0) {
508         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
509             break;
510         }
511         curCount = impl->mWeak;
512     }
513
514     if (curCount > 0) {
515         impl->addWeakRef(id);
516     }
517
518     return curCount > 0;
519 }
520
521 int32_t RefBase::weakref_type::getWeakCount() const
522 {
523     return static_cast<const weakref_impl*>(this)->mWeak;
524 }
525
526 void RefBase::weakref_type::printRefs() const
527 {
528     static_cast<const weakref_impl*>(this)->printRefs();
529 }
530
531 void RefBase::weakref_type::trackMe(bool enable, bool retain)
532 {
533     static_cast<const weakref_impl*>(this)->trackMe(enable, retain);
534 }
535
536 RefBase::weakref_type* RefBase::createWeak(const void* id) const
537 {
538     mRefs->incWeak(id);
539     return mRefs;
540 }
541
542 RefBase::weakref_type* RefBase::getWeakRefs() const
543 {
544     return mRefs;
545 }
546
547 RefBase::RefBase()
548     : mRefs(new weakref_impl(this))
549 {
550 }
551
552 RefBase::~RefBase()
553 {
554     if (mRefs->mWeak == 0) {
555         delete mRefs;
556     }
557 }
558
559 void RefBase::extendObjectLifetime(int32_t mode)
560 {
561     android_atomic_or(mode, &mRefs->mFlags);
562 }
563
564 void RefBase::onFirstRef()
565 {
566 }
567
568 void RefBase::onLastStrongRef(const void* /*id*/)
569 {
570 }
571
572 bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
573 {
574     return (flags&FIRST_INC_STRONG) ? true : false;
575 }
576
577 void RefBase::onLastWeakRef(const void* /*id*/)
578 {
579 }
580
581 // ---------------------------------------------------------------------------
582
583 void RefBase::moveReferences(void* dst, void const* src, size_t n,
584         const ReferenceConverterBase& caster)
585 {
586 #if DEBUG_REFS
587     const size_t itemSize = caster.getReferenceTypeSize();
588     for (size_t i=0 ; i<n ; i++) {
589         void*       d = reinterpret_cast<void      *>(intptr_t(dst) + i*itemSize);
590         void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize);
591         RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d)));
592         ref->mRefs->renameStrongRefId(s, d);
593         ref->mRefs->renameWeakRefId(s, d);
594     }
595 #endif
596 }
597
598 // ---------------------------------------------------------------------------
599
600 TextOutput& printStrongPointer(TextOutput& to, const void* val)
601 {
602     to << "sp<>(" << val << ")";
603     return to;
604 }
605
606 TextOutput& printWeakPointer(TextOutput& to, const void* val)
607 {
608     to << "wp<>(" << val << ")";
609     return to;
610 }
611
612
613 }; // namespace android