From 777ec2662ef5ee8b0a501e0b8a9b2d7a2b84ffe7 Mon Sep 17 00:00:00 2001 From: Jason Sams Date: Thu, 18 Aug 2011 18:01:33 -0700 Subject: Fix issue with freeing allocation with circular references. Change-Id: I45871c20a192815eafee77f95e17a025f6dcf9d1 --- libs/rs/rsAllocation.cpp | 27 ++++++++++++++------------- libs/rs/rsAllocation.h | 2 ++ libs/rs/rsContext.cpp | 1 + libs/rs/rsObjectBase.cpp | 26 ++++++++++++++++++++++++++ libs/rs/rsObjectBase.h | 2 ++ libs/rs/rsProgram.cpp | 21 +++++++++++++-------- libs/rs/rsProgram.h | 1 + 7 files changed, 59 insertions(+), 21 deletions(-) diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index a366d49..4359d95 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -58,19 +58,7 @@ void Allocation::updateCache() { } Allocation::~Allocation() { - if (mHal.state.hasReferences && - (mHal.state.hasFaces || mHal.state.hasMipmaps)) { - LOGE("Cube/mip allocation with references unsupported, memory not cleaned up!"); - } - - uint32_t elemCount = mHal.state.dimensionX; - if (mHal.state.dimensionY > 1) { - elemCount *= mHal.state.dimensionY; - } - if (mHal.state.dimensionZ > 1) { - elemCount *= mHal.state.dimensionZ; - } - decRefs(getPtr(), elemCount, 0); + freeChildrenUnlocked(); mRSC->mHal.funcs.allocation.destroy(mRSC, this); } @@ -299,6 +287,19 @@ void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const { } } +void Allocation::freeChildrenUnlocked () { + decRefs(getPtr(), mHal.state.type->getSizeBytes() / mHal.state.type->getElementSizeBytes(), 0); +} + +bool Allocation::freeChildren() { + if (mHal.state.hasReferences) { + incSysRef(); + freeChildrenUnlocked(); + return decSysRef(); + } + return false; +} + void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) { } diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h index f2589c0..67fc3b5 100644 --- a/libs/rs/rsAllocation.h +++ b/libs/rs/rsAllocation.h @@ -116,6 +116,7 @@ public: void incRefs(const void *ptr, size_t ct, size_t startOff = 0) const; void decRefs(const void *ptr, size_t ct, size_t startOff = 0) const; + virtual bool freeChildren(); void sendDirty(const Context *rsc) const; bool getHasGraphicsMipmaps() const { @@ -127,6 +128,7 @@ protected: Vector mToDirtyList; private: + void freeChildrenUnlocked(); Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc); }; diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 8996ad1..e3a9cf8 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -312,6 +312,7 @@ void Context::destroyWorkerThreadResources() { mStateSampler.deinit(this); mFBOCache.deinit(this); } + ObjectBase::freeAllChildren(this); //LOGV("destroyWorkerThreadResources 2"); mExit = true; } diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp index f428f94..f5ced26 100644 --- a/libs/rs/rsObjectBase.cpp +++ b/libs/rs/rsObjectBase.cpp @@ -81,6 +81,10 @@ void ObjectBase::incSysRef() const { void ObjectBase::preDestroy() const { } +bool ObjectBase::freeChildren() { + return false; +} + bool ObjectBase::checkDelete(const ObjectBase *ref) { if (!ref) { return false; @@ -217,6 +221,28 @@ void ObjectBase::zeroAllUserRef(Context *rsc) { } } +void ObjectBase::freeAllChildren(Context *rsc) { + if (rsc->props.mLogObjects) { + LOGV("Forcing release of all child objects."); + } + + // This operation can be slow, only to be called during context cleanup. + ObjectBase * o = (ObjectBase *)rsc->mObjHead; + while (o) { + if (o->freeChildren()) { + // deleted ref to self and possibly others, restart from head. + o = (ObjectBase *)rsc->mObjHead; + } else { + o = (ObjectBase *)o->mNext; + } + } + + if (rsc->props.mLogObjects) { + LOGV("Objects remaining."); + dumpAll(rsc); + } +} + void ObjectBase::dumpAll(Context *rsc) { asyncLock(); diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h index c7cfb0e..d9f5f3b 100644 --- a/libs/rs/rsObjectBase.h +++ b/libs/rs/rsObjectBase.h @@ -50,8 +50,10 @@ public: void setName(const char *, uint32_t len); Context * getContext() const {return mRSC;} + virtual bool freeChildren(); static void zeroAllUserRef(Context *rsc); + static void freeAllChildren(Context *rsc); static void dumpAll(Context *rsc); virtual void dumpLOGV(const char *prefix) const; diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp index 33eb422..4178aa5 100644 --- a/libs/rs/rsProgram.cpp +++ b/libs/rs/rsProgram.cpp @@ -70,15 +70,8 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, } Program::~Program() { + freeChildren(); - for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) { - bindAllocation(NULL, NULL, ct); - } - - for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) { - bindTexture(NULL, ct, NULL); - bindSampler(NULL, ct, NULL); - } delete[] mHal.state.textures; delete[] mHal.state.samplers; delete[] mHal.state.textureTargets; @@ -90,6 +83,18 @@ Program::~Program() { mHal.state.texturesCount = 0; } +bool Program::freeChildren() { + for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) { + bindAllocation(NULL, NULL, ct); + } + + for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) { + bindTexture(NULL, ct, NULL); + bindSampler(NULL, ct, NULL); + } + return false; +} + void Program::initMemberVars() { mDirty = true; diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h index 948ba3e..3237a72 100644 --- a/libs/rs/rsProgram.h +++ b/libs/rs/rsProgram.h @@ -34,6 +34,7 @@ public: Program(Context *, const char * shaderText, uint32_t shaderLength, const uint32_t * params, uint32_t paramLength); virtual ~Program(); + virtual bool freeChildren(); void bindAllocation(Context *, Allocation *, uint32_t slot); -- cgit v1.1