rsObjectBase.cpp 7.9 KB

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