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     //ALOGV("~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     //ALOGV("calling add  rsc %p", mRSC);
    182     mNext = mRSC->mObjHead;
    183     if (mRSC->mObjHead) {
    184         mRSC->mObjHead->mPrev = this;
    185     }
    186     mRSC->mObjHead = this;
    187 
    188     asyncUnlock();
    189 }
    190 
    191 void ObjectBase::remove() const {
    192     //ALOGV("calling remove  rsc %p", mRSC);
    193     if (!mRSC) {
    194         rsAssert(!mPrev);
    195         rsAssert(!mNext);
    196         return;
    197     }
    198 
    199     if (mRSC->mObjHead == this) {
    200         mRSC->mObjHead = mNext;
    201     }
    202     if (mPrev) {
    203         mPrev->mNext = mNext;
    204     }
    205     if (mNext) {
    206         mNext->mPrev = mPrev;
    207     }
    208     mPrev = NULL;
    209     mNext = NULL;
    210 }
    211 
    212 void ObjectBase::zeroAllUserRef(Context *rsc) {
    213     if (rsc->props.mLogObjects) {
    214         ALOGV("Forcing release of all outstanding user refs.");
    215     }
    216 
    217     // This operation can be slow, only to be called during context cleanup.
    218     const ObjectBase * o = rsc->mObjHead;
    219     while (o) {
    220         //ALOGE("o %p", o);
    221         if (o->zeroUserRef()) {
    222             // deleted the object and possibly others, restart from head.
    223             o = rsc->mObjHead;
    224             //ALOGE("o head %p", o);
    225         } else {
    226             o = o->mNext;
    227             //ALOGE("o next %p", o);
    228         }
    229     }
    230 
    231     if (rsc->props.mLogObjects) {
    232         ALOGV("Objects remaining.");
    233         dumpAll(rsc);
    234     }
    235 }
    236 
    237 void ObjectBase::freeAllChildren(Context *rsc) {
    238     if (rsc->props.mLogObjects) {
    239         ALOGV("Forcing release of all child objects.");
    240     }
    241 
    242     // This operation can be slow, only to be called during context cleanup.
    243     ObjectBase * o = (ObjectBase *)rsc->mObjHead;
    244     while (o) {
    245         if (o->freeChildren()) {
    246             // deleted ref to self and possibly others, restart from head.
    247             o = (ObjectBase *)rsc->mObjHead;
    248         } else {
    249             o = (ObjectBase *)o->mNext;
    250         }
    251     }
    252 
    253     if (rsc->props.mLogObjects) {
    254         ALOGV("Objects remaining.");
    255         dumpAll(rsc);
    256     }
    257 }
    258 
    259 void ObjectBase::dumpAll(Context *rsc) {
    260     asyncLock();
    261 
    262     ALOGV("Dumping all objects");
    263     const ObjectBase * o = rsc->mObjHead;
    264     while (o) {
    265         ALOGV(" Object %p", o);
    266         o->dumpLOGV("  ");
    267         o = o->mNext;
    268     }
    269 
    270     asyncUnlock();
    271 }
    272 
    273 bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj) {
    274     asyncLock();
    275 
    276     const ObjectBase * o = rsc->mObjHead;
    277     while (o) {
    278         if (o == obj) {
    279             asyncUnlock();
    280             return true;
    281         }
    282         o = o->mNext;
    283     }
    284     asyncUnlock();
    285     return false;
    286 }
    287