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