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