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