blob: 714cf8095392c15aaedb8077397bb079a8e1a0f3 [file] [log] [blame]
Jason Sams326e0dd2009-05-22 14:03:28 -07001/*
2 * Copyright (C) 2009 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#include "rsObjectBase.h"
Jason Samse514b452009-09-25 14:51:22 -070018#include "rsContext.h"
Jason Sams84bf95d2015-04-09 14:36:37 -070019#include "rsDebugHelper.h"
Jason Sams225afd32010-10-21 14:06:55 -070020
Chih-Hung Hsieh11496ac2016-11-15 15:14:05 -080021namespace android {
22namespace renderscript {
Jason Sams326e0dd2009-05-22 14:03:28 -070023
Jason Sams2353ae32010-10-14 17:48:46 -070024pthread_mutex_t ObjectBase::gObjectInitMutex = PTHREAD_MUTEX_INITIALIZER;
25
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080026ObjectBase::ObjectBase(Context *rsc) {
Jason Sams9397e302009-08-27 20:23:34 -070027 mUserRefCount = 0;
28 mSysRefCount = 0;
Jason Sams2353ae32010-10-14 17:48:46 -070029 mRSC = rsc;
Chris Wailes44bef6f2014-08-12 13:51:10 -070030 mNext = nullptr;
31 mPrev = nullptr;
32 mDH = nullptr;
33 mName = nullptr;
Jason Sams225afd32010-10-21 14:06:55 -070034
Jason Sams84bf95d2015-04-09 14:36:37 -070035 if (gDebugStacks || gDebugReferences || gDebugLeaks) {
36 mDH = new DebugHelper();
37 }
Jason Sams2353ae32010-10-14 17:48:46 -070038
39 rsAssert(rsc);
40 add();
Jason Sams84bf95d2015-04-09 14:36:37 -070041
42 if (gDebugLifetime || gDebugReferences) {
43 ALOGV("ObjectBase constructed %p", this);
44 }
Jason Sams326e0dd2009-05-22 14:03:28 -070045}
46
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080047ObjectBase::~ObjectBase() {
Jason Sams84bf95d2015-04-09 14:36:37 -070048 if (gDebugLifetime || gDebugReferences) {
49 ALOGV("ObjectBase destroyed %p refs %i %i", this, mUserRefCount, mSysRefCount);
50 }
51
52 if (gDebugStacks || gDebugReferences || gDebugLeaks) {
53 if (gDebugStacks || gDebugReferences) {
54 mDH->dump();
55 }
56 delete mDH;
57 mDH = nullptr;
58 }
Jason Sams225afd32010-10-21 14:06:55 -070059
Stephen Hinesb0934b62013-07-03 17:27:38 -070060 free(const_cast<char *>(mName));
61
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080062 if (mPrev || mNext) {
Jason Sams225afd32010-10-21 14:06:55 -070063 // While the normal practice is to call remove before we call
64 // delete. Its possible for objects without a re-use list
65 // for avoiding duplication to be created on the stack. In those
66 // cases we need to remove ourself here.
67 asyncLock();
68 remove();
69 asyncUnlock();
70 }
71
Jason Sams9397e302009-08-27 20:23:34 -070072 rsAssert(!mUserRefCount);
73 rsAssert(!mSysRefCount);
Jason Samse514b452009-09-25 14:51:22 -070074}
75
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080076void ObjectBase::dumpLOGV(const char *op) const {
Stephen Hinesb0934b62013-07-03 17:27:38 -070077 if (mName) {
Steve Block65982012011-10-20 11:56:00 +010078 ALOGV("%s RSobj %p, name %s, refs %i,%i links %p,%p,%p",
Stephen Hinesb0934b62013-07-03 17:27:38 -070079 op, this, mName, mUserRefCount, mSysRefCount, mNext, mPrev, mRSC);
Jason Samsf2649a92009-09-25 16:37:33 -070080 } else {
Steve Block65982012011-10-20 11:56:00 +010081 ALOGV("%s RSobj %p, no-name, refs %i,%i links %p,%p,%p",
Jason Sams225afd32010-10-21 14:06:55 -070082 op, this, mUserRefCount, mSysRefCount, mNext, mPrev, mRSC);
Jason Samsf2649a92009-09-25 16:37:33 -070083 }
84}
85
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080086void ObjectBase::incUserRef() const {
Tim Murray0b575de2013-03-15 15:56:43 -070087 __sync_fetch_and_add(&mUserRefCount, 1);
Jason Sams84bf95d2015-04-09 14:36:37 -070088 if (gDebugReferences) {
89 ALOGV("ObjectBase %p incU ref %i, %i", this, mUserRefCount, mSysRefCount);
90 }
Jason Sams2353ae32010-10-14 17:48:46 -070091}
92
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080093void ObjectBase::incSysRef() const {
Tim Murray0b575de2013-03-15 15:56:43 -070094 __sync_fetch_and_add(&mSysRefCount, 1);
Jason Sams84bf95d2015-04-09 14:36:37 -070095 if (gDebugReferences) {
96 ALOGV("ObjectBase %p incS ref %i, %i", this, mUserRefCount, mSysRefCount);
97 }
Jason Sams9397e302009-08-27 20:23:34 -070098}
99
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800100void ObjectBase::preDestroy() const {
Jason Sams225afd32010-10-21 14:06:55 -0700101}
Jason Sams2353ae32010-10-14 17:48:46 -0700102
Jason Samsc7cec1e2011-08-18 18:01:33 -0700103bool ObjectBase::freeChildren() {
104 return false;
105}
106
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800107bool ObjectBase::checkDelete(const ObjectBase *ref) {
Jason Sams225afd32010-10-21 14:06:55 -0700108 if (!ref) {
109 return false;
110 }
Jason Sams2353ae32010-10-14 17:48:46 -0700111
Jason Sams225afd32010-10-21 14:06:55 -0700112 asyncLock();
113 // This lock protects us against the non-RS threads changing
114 // the ref counts. At this point we should be the only thread
115 // working on them.
116 if (ref->mUserRefCount || ref->mSysRefCount) {
117 asyncUnlock();
118 return false;
119 }
120
121 ref->remove();
122 // At this point we can unlock because there should be no possible way
123 // for another thread to reference this object.
124 ref->preDestroy();
125 asyncUnlock();
126 delete ref;
127 return true;
128}
129
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800130bool ObjectBase::decUserRef() const {
Jason Sams225afd32010-10-21 14:06:55 -0700131 rsAssert(mUserRefCount > 0);
Jason Sams84bf95d2015-04-09 14:36:37 -0700132 if (gDebugReferences) {
133 ALOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount);
134 if (mUserRefCount <= 0) {
135 mDH->dump();
136 }
Jason Samsf0c1df42010-10-26 13:09:17 -0700137 }
Jason Samsf0c1df42010-10-26 13:09:17 -0700138
139
Tim Murray0b575de2013-03-15 15:56:43 -0700140 if ((__sync_fetch_and_sub(&mUserRefCount, 1) <= 1)) {
141 __sync_synchronize();
142 if (mSysRefCount <= 0) {
143 return checkDelete(this);
144 }
Jason Samse514b452009-09-25 14:51:22 -0700145 }
146 return false;
147}
148
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800149bool ObjectBase::zeroUserRef() const {
Jason Sams84bf95d2015-04-09 14:36:37 -0700150 if (gDebugReferences) {
151 ALOGV("ObjectBase %p zeroU ref %i, %i", this, mUserRefCount, mSysRefCount);
152 }
153
Tim Murray0b575de2013-03-15 15:56:43 -0700154 __sync_and_and_fetch(&mUserRefCount, 0);
Stephen Hines61c86952013-04-09 17:34:43 -0700155 if (mSysRefCount <= 0) {
156 return checkDelete(this);
Jason Sams225afd32010-10-21 14:06:55 -0700157 }
158 return false;
Jason Samse514b452009-09-25 14:51:22 -0700159}
160
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800161bool ObjectBase::decSysRef() const {
Jason Sams84bf95d2015-04-09 14:36:37 -0700162 if (gDebugReferences) {
163 ALOGV("ObjectBase %p decS ref %i, %i", this, mUserRefCount, mSysRefCount);
164 }
165
Jason Sams9397e302009-08-27 20:23:34 -0700166 rsAssert(mSysRefCount > 0);
Tim Murray0b575de2013-03-15 15:56:43 -0700167 if ((__sync_fetch_and_sub(&mSysRefCount, 1) <= 1)) {
168 __sync_synchronize();
169 if (mUserRefCount <= 0) {
170 return checkDelete(this);
171 }
Jason Sams225afd32010-10-21 14:06:55 -0700172 }
173 return false;
Jason Sams326e0dd2009-05-22 14:03:28 -0700174}
175
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800176void ObjectBase::setName(const char *name) {
Stephen Hinesb0934b62013-07-03 17:27:38 -0700177 mName = strdup(name);
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700178}
Jason Samsa4a54e42009-06-10 18:39:40 -0700179
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800180void ObjectBase::setName(const char *name, uint32_t len) {
Stephen Hinesb0934b62013-07-03 17:27:38 -0700181 char *c = (char*)calloc(len + 1, sizeof(char));
182 rsAssert(c);
183 memcpy(c, name, len);
184 mName = c;
Jason Samsa4a54e42009-06-10 18:39:40 -0700185}
186
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800187void ObjectBase::asyncLock() {
Jason Sams2353ae32010-10-14 17:48:46 -0700188 pthread_mutex_lock(&gObjectInitMutex);
189}
190
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800191void ObjectBase::asyncUnlock() {
Jason Sams2353ae32010-10-14 17:48:46 -0700192 pthread_mutex_unlock(&gObjectInitMutex);
193}
194
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800195void ObjectBase::add() const {
Jason Sams225afd32010-10-21 14:06:55 -0700196 asyncLock();
Jason Sams2353ae32010-10-14 17:48:46 -0700197
Jason Samse514b452009-09-25 14:51:22 -0700198 rsAssert(!mNext);
199 rsAssert(!mPrev);
Jason Samse514b452009-09-25 14:51:22 -0700200 mNext = mRSC->mObjHead;
201 if (mRSC->mObjHead) {
202 mRSC->mObjHead->mPrev = this;
203 }
204 mRSC->mObjHead = this;
Jason Sams2353ae32010-10-14 17:48:46 -0700205
Jason Sams225afd32010-10-21 14:06:55 -0700206 asyncUnlock();
Jason Samse514b452009-09-25 14:51:22 -0700207}
208
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800209void ObjectBase::remove() const {
Jason Samse514b452009-09-25 14:51:22 -0700210 if (!mRSC) {
211 rsAssert(!mPrev);
212 rsAssert(!mNext);
213 return;
214 }
Jason Sams2353ae32010-10-14 17:48:46 -0700215
Jason Samse514b452009-09-25 14:51:22 -0700216 if (mRSC->mObjHead == this) {
217 mRSC->mObjHead = mNext;
218 }
219 if (mPrev) {
220 mPrev->mNext = mNext;
221 }
222 if (mNext) {
223 mNext->mPrev = mPrev;
224 }
Chris Wailes44bef6f2014-08-12 13:51:10 -0700225 mPrev = nullptr;
226 mNext = nullptr;
Jason Samse514b452009-09-25 14:51:22 -0700227}
228
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800229void ObjectBase::zeroAllUserRef(Context *rsc) {
Jason Sams84bf95d2015-04-09 14:36:37 -0700230 if (gDebugReferences || gDebugLeaks) {
Steve Block65982012011-10-20 11:56:00 +0100231 ALOGV("Forcing release of all outstanding user refs.");
Jason Sams1fddd902009-09-25 15:25:00 -0700232 }
Jason Samse514b452009-09-25 14:51:22 -0700233
234 // This operation can be slow, only to be called during context cleanup.
235 const ObjectBase * o = rsc->mObjHead;
236 while (o) {
Steve Blockaf12ac62012-01-06 19:20:56 +0000237 //ALOGE("o %p", o);
Jason Samse514b452009-09-25 14:51:22 -0700238 if (o->zeroUserRef()) {
George Burgess IV12dbbaa2017-08-22 17:16:09 -0700239#ifdef __clang_analyzer__
240 // Assure the static analyzer that we updated mObjHead. Otherwise,
241 // it complains about a use-after-free here. Needed for b/27101951.
242 if (o == rsc->mObjHead) {
243 abort();
244 }
245#endif
Jason Samse514b452009-09-25 14:51:22 -0700246 // deleted the object and possibly others, restart from head.
247 o = rsc->mObjHead;
Steve Blockaf12ac62012-01-06 19:20:56 +0000248 //ALOGE("o head %p", o);
Jason Samse514b452009-09-25 14:51:22 -0700249 } else {
250 o = o->mNext;
Steve Blockaf12ac62012-01-06 19:20:56 +0000251 //ALOGE("o next %p", o);
Jason Samse514b452009-09-25 14:51:22 -0700252 }
253 }
Jason Samsf2649a92009-09-25 16:37:33 -0700254
Jason Sams84bf95d2015-04-09 14:36:37 -0700255 if (gDebugReferences || gDebugLeaks) {
Steve Block65982012011-10-20 11:56:00 +0100256 ALOGV("Objects remaining.");
Jason Sams25afc002009-11-19 13:08:17 -0800257 dumpAll(rsc);
Jason Samsf2649a92009-09-25 16:37:33 -0700258 }
Jason Samse514b452009-09-25 14:51:22 -0700259}
260
Jason Samsc7cec1e2011-08-18 18:01:33 -0700261void ObjectBase::freeAllChildren(Context *rsc) {
Jason Sams84bf95d2015-04-09 14:36:37 -0700262 if (gDebugReferences) {
Steve Block65982012011-10-20 11:56:00 +0100263 ALOGV("Forcing release of all child objects.");
Jason Samsc7cec1e2011-08-18 18:01:33 -0700264 }
265
266 // This operation can be slow, only to be called during context cleanup.
267 ObjectBase * o = (ObjectBase *)rsc->mObjHead;
268 while (o) {
269 if (o->freeChildren()) {
270 // deleted ref to self and possibly others, restart from head.
271 o = (ObjectBase *)rsc->mObjHead;
272 } else {
273 o = (ObjectBase *)o->mNext;
274 }
275 }
276
Jason Sams84bf95d2015-04-09 14:36:37 -0700277 if (gDebugReferences) {
Steve Block65982012011-10-20 11:56:00 +0100278 ALOGV("Objects remaining.");
Jason Samsc7cec1e2011-08-18 18:01:33 -0700279 dumpAll(rsc);
280 }
281}
282
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800283void ObjectBase::dumpAll(Context *rsc) {
Jason Sams225afd32010-10-21 14:06:55 -0700284 asyncLock();
Jason Sams2353ae32010-10-14 17:48:46 -0700285
Steve Block65982012011-10-20 11:56:00 +0100286 ALOGV("Dumping all objects");
Jason Sams25afc002009-11-19 13:08:17 -0800287 const ObjectBase * o = rsc->mObjHead;
288 while (o) {
Steve Block65982012011-10-20 11:56:00 +0100289 ALOGV(" Object %p", o);
Jason Sams25afc002009-11-19 13:08:17 -0800290 o->dumpLOGV(" ");
Jason Sams84bf95d2015-04-09 14:36:37 -0700291 if (o->mDH != nullptr) {
292 o->mDH->dump();
293 }
Jason Sams25afc002009-11-19 13:08:17 -0800294 o = o->mNext;
Jason Samsc21cf402009-11-17 17:26:46 -0800295 }
Jason Sams2353ae32010-10-14 17:48:46 -0700296
Jason Sams225afd32010-10-21 14:06:55 -0700297 asyncUnlock();
Jason Samsc21cf402009-11-17 17:26:46 -0800298}
299
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800300bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj) {
Jason Sams225afd32010-10-21 14:06:55 -0700301 asyncLock();
Jason Sams2353ae32010-10-14 17:48:46 -0700302
Jason Sams605048a2010-09-30 18:15:52 -0700303 const ObjectBase * o = rsc->mObjHead;
304 while (o) {
305 if (o == obj) {
Jason Sams225afd32010-10-21 14:06:55 -0700306 asyncUnlock();
Jason Sams605048a2010-09-30 18:15:52 -0700307 return true;
308 }
309 o = o->mNext;
310 }
Jason Sams225afd32010-10-21 14:06:55 -0700311 asyncUnlock();
Jason Sams605048a2010-09-30 18:15:52 -0700312 return false;
313}
Jason Samsa36c50a2014-06-17 12:06:06 -0700314
315void ObjectBase::callUpdateCacheObject(const Context *rsc, void *dstObj) const {
316 //ALOGE("ObjectBase::callUpdateCacheObject %p %p", this, dstObj);
317 *((const void **)dstObj) = this;
318}
319
Chih-Hung Hsieh11496ac2016-11-15 15:14:05 -0800320} // namespace renderscript
321} // namespace android