rsObjectBase.cpp revision 77d9f4bd05b2d2a161f30c12a2248f9c97eaac42
1/* 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" 18#include "rsContext.h" 19 20using namespace android; 21using namespace android::renderscript; 22 23pthread_mutex_t ObjectBase::gObjectInitMutex = PTHREAD_MUTEX_INITIALIZER; 24 25ObjectBase::ObjectBase(Context *rsc) { 26 mUserRefCount = 0; 27 mSysRefCount = 0; 28 mRSC = rsc; 29 mNext = NULL; 30 mPrev = NULL; 31 32#if RS_OBJECT_DEBUG 33 mStack.update(2); 34#endif 35 36 rsAssert(rsc); 37 add(); 38 //LOGV("ObjectBase %p con", this); 39} 40 41ObjectBase::~ObjectBase() { 42 //LOGV("~ObjectBase %p ref %i,%i", this, mUserRefCount, mSysRefCount); 43#if RS_OBJECT_DEBUG 44 mStack.dump(); 45#endif 46 47 if (mPrev || mNext) { 48 // While the normal practice is to call remove before we call 49 // delete. Its possible for objects without a re-use list 50 // for avoiding duplication to be created on the stack. In those 51 // cases we need to remove ourself here. 52 asyncLock(); 53 remove(); 54 asyncUnlock(); 55 } 56 57 rsAssert(!mUserRefCount); 58 rsAssert(!mSysRefCount); 59} 60 61void ObjectBase::dumpLOGV(const char *op) const { 62 if (mName.size()) { 63 LOGV("%s RSobj %p, name %s, refs %i,%i links %p,%p,%p", 64 op, this, mName.string(), mUserRefCount, mSysRefCount, mNext, mPrev, mRSC); 65 } else { 66 LOGV("%s RSobj %p, no-name, refs %i,%i links %p,%p,%p", 67 op, this, mUserRefCount, mSysRefCount, mNext, mPrev, mRSC); 68 } 69} 70 71void ObjectBase::incUserRef() const { 72 android_atomic_inc(&mUserRefCount); 73 //LOGV("ObjectBase %p incU ref %i, %i", this, mUserRefCount, mSysRefCount); 74} 75 76void ObjectBase::incSysRef() const { 77 android_atomic_inc(&mSysRefCount); 78 //LOGV("ObjectBase %p incS ref %i, %i", this, mUserRefCount, mSysRefCount); 79} 80 81void ObjectBase::preDestroy() const { 82} 83 84bool ObjectBase::checkDelete(const ObjectBase *ref) { 85 if (!ref) { 86 return false; 87 } 88 89 asyncLock(); 90 // This lock protects us against the non-RS threads changing 91 // the ref counts. At this point we should be the only thread 92 // working on them. 93 if (ref->mUserRefCount || ref->mSysRefCount) { 94 asyncUnlock(); 95 return false; 96 } 97 98 ref->remove(); 99 // At this point we can unlock because there should be no possible way 100 // for another thread to reference this object. 101 ref->preDestroy(); 102 asyncUnlock(); 103 delete ref; 104 return true; 105} 106 107bool ObjectBase::decUserRef() const { 108 rsAssert(mUserRefCount > 0); 109#if RS_OBJECT_DEBUG 110 LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount); 111 if (mUserRefCount <= 0) { 112 mStack.dump(); 113 } 114#endif 115 116 117 if ((android_atomic_dec(&mUserRefCount) <= 1) && 118 (android_atomic_acquire_load(&mSysRefCount) <= 0)) { 119 return checkDelete(this); 120 } 121 return false; 122} 123 124bool ObjectBase::zeroUserRef() const { 125 //LOGV("ObjectBase %p zeroU ref %i, %i", this, mUserRefCount, mSysRefCount); 126 android_atomic_acquire_store(0, &mUserRefCount); 127 if (android_atomic_acquire_load(&mSysRefCount) <= 0) { 128 return checkDelete(this); 129 } 130 return false; 131} 132 133bool ObjectBase::decSysRef() const { 134 //LOGV("ObjectBase %p decS ref %i, %i", this, mUserRefCount, mSysRefCount); 135 rsAssert(mSysRefCount > 0); 136 if ((android_atomic_dec(&mSysRefCount) <= 1) && 137 (android_atomic_acquire_load(&mUserRefCount) <= 0)) { 138 return checkDelete(this); 139 } 140 return false; 141} 142 143void ObjectBase::setName(const char *name) { 144 mName.setTo(name); 145} 146 147void ObjectBase::setName(const char *name, uint32_t len) { 148 mName.setTo(name, len); 149} 150 151void ObjectBase::asyncLock() { 152 pthread_mutex_lock(&gObjectInitMutex); 153} 154 155void ObjectBase::asyncUnlock() { 156 pthread_mutex_unlock(&gObjectInitMutex); 157} 158 159void ObjectBase::add() const { 160 asyncLock(); 161 162 rsAssert(!mNext); 163 rsAssert(!mPrev); 164 //LOGV("calling add rsc %p", mRSC); 165 mNext = mRSC->mObjHead; 166 if (mRSC->mObjHead) { 167 mRSC->mObjHead->mPrev = this; 168 } 169 mRSC->mObjHead = this; 170 171 asyncUnlock(); 172} 173 174void ObjectBase::remove() const { 175 //LOGV("calling remove rsc %p", mRSC); 176 if (!mRSC) { 177 rsAssert(!mPrev); 178 rsAssert(!mNext); 179 return; 180 } 181 182 if (mRSC->mObjHead == this) { 183 mRSC->mObjHead = mNext; 184 } 185 if (mPrev) { 186 mPrev->mNext = mNext; 187 } 188 if (mNext) { 189 mNext->mPrev = mPrev; 190 } 191 mPrev = NULL; 192 mNext = NULL; 193} 194 195void ObjectBase::zeroAllUserRef(Context *rsc) { 196 if (rsc->props.mLogObjects) { 197 LOGV("Forcing release of all outstanding user refs."); 198 } 199 200 // This operation can be slow, only to be called during context cleanup. 201 const ObjectBase * o = rsc->mObjHead; 202 while (o) { 203 //LOGE("o %p", o); 204 if (o->zeroUserRef()) { 205 // deleted the object and possibly others, restart from head. 206 o = rsc->mObjHead; 207 //LOGE("o head %p", o); 208 } else { 209 o = o->mNext; 210 //LOGE("o next %p", o); 211 } 212 } 213 214 if (rsc->props.mLogObjects) { 215 LOGV("Objects remaining."); 216 dumpAll(rsc); 217 } 218} 219 220void ObjectBase::dumpAll(Context *rsc) { 221 asyncLock(); 222 223 LOGV("Dumping all objects"); 224 const ObjectBase * o = rsc->mObjHead; 225 while (o) { 226 LOGV(" Object %p", o); 227 o->dumpLOGV(" "); 228 o = o->mNext; 229 } 230 231 asyncUnlock(); 232} 233 234bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj) { 235 asyncLock(); 236 237 const ObjectBase * o = rsc->mObjHead; 238 while (o) { 239 if (o == obj) { 240 asyncUnlock(); 241 return true; 242 } 243 o = o->mNext; 244 } 245 asyncUnlock(); 246 return false; 247} 248 249