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