Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a4c8392 authored by The Android Open Source Project's avatar The Android Open Source Project Committed by Alex Ray
Browse files

auto import from //depot/cupcake/@136594

parent cbb1011c
Loading
Loading
Loading
Loading
+0 −35
Original line number Diff line number Diff line
@@ -248,41 +248,6 @@ private:
};


/*
 * Read/write lock.  The resource can have multiple readers or one writer,
 * but can't be read and written at the same time.
 *
 * The same thread should not call a lock function while it already has
 * a lock.  (Should be okay for multiple readers.)
 */
class ReadWriteLock {
public:
    ReadWriteLock()
        : mNumReaders(0), mNumWriters(0)
        {}
    ~ReadWriteLock() {}

    void lockForRead();
    bool tryLockForRead();
    void unlockForRead();

    void lockForWrite();
    bool tryLockForWrite();
    void unlockForWrite();

private:
    int         mNumReaders;
    int         mNumWriters;

    Mutex       mLock;
    Condition   mReadWaiter;
    Condition   mWriteWaiter;
#if defined(PRINT_RENDER_TIMES)
    DurationTimer mDebugTimer;
#endif
};


/*
 * This is our spiffy thread object!
 */
+19 −6
Original line number Diff line number Diff line
@@ -120,13 +120,18 @@ class MapInfo {
        char name[];
    };

    const char *map_to_name(uint64_t pc, const char* def) {
    const char *map_to_name(uint64_t pc, const char* def, uint64_t* start) {
        mapinfo* mi = getMapInfoList();
        while(mi) {
            if ((pc >= mi->start) && (pc < mi->end))
            if ((pc >= mi->start) && (pc < mi->end)) {
                if (start) 
                    *start = mi->start;
                return mi->name;
            }
            mi = mi->next;
        }
        if (start) 
            *start = 0;
        return def;
    }

@@ -183,8 +188,15 @@ public:
        }
    }
    
    static const char *mapAddressToName(const void* pc, const char* def) {
        return sMapInfo.map_to_name((uint64_t)pc, def);
    static const char *mapAddressToName(const void* pc, const char* def,
            void const** start) 
    {
        uint64_t s;
        char const* name = sMapInfo.map_to_name(uint64_t(uintptr_t(pc)), def, &s);
        if (start) {
            *start = (void*)s;
        }
        return name;
    }

};
@@ -297,8 +309,9 @@ String8 CallStack::toStringSingleLevel(const char* prefix, int32_t level) const
        res.append(name);
        res.append(tmp2);
    } else { 
        name = MapInfo::mapAddressToName(ip, "<unknown>");
        snprintf(tmp, 256, "pc %p  %s", ip, name);
        void const* start = 0;
        name = MapInfo::mapAddressToName(ip, "<unknown>", &start);
        snprintf(tmp, 256, "pc %08lx  %s", uintptr_t(ip)-uintptr_t(start), name);
        res.append(tmp);
    }
    res.append("\n");
+8 −6
Original line number Diff line number Diff line
@@ -176,7 +176,9 @@ size_t Res_png_9patch::serializedSize()

void* Res_png_9patch::serialize()
{
    void* newData = malloc(serializedSize());
    // Use calloc since we're going to leave a few holes in the data
    // and want this to run cleanly under valgrind
    void* newData = calloc(1, serializedSize());
    serialize(newData);
    return newData;
}
@@ -3150,7 +3152,7 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
            const char16_t* pos = s;
            while (pos < end && !failed) {
                const char16_t* start = pos;
                end++;
                pos++;
                while (pos < end && *pos != '|') {
                    pos++;
                }
+1 −1
Original line number Diff line number Diff line
@@ -388,7 +388,7 @@ status_t String16::setTo(const char16_t* other, size_t len)
        ->editResize((len+1)*sizeof(char16_t));
    if (buf) {
        char16_t* str = (char16_t*)buf->data();
        memcpy(str, other, len*sizeof(char16_t));
        memmove(str, other, len*sizeof(char16_t));
        str[len] = 0;
        mString = str;
        return NO_ERROR;
+50 −176
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 */

// #define LOG_NDEBUG 0
#define LOG_TAG "libutils.threads"

#include <utils/threads.h>
@@ -838,148 +839,6 @@ void Condition::broadcast()
#error "condition variables not supported on this platform"
#endif


/*
 * ===========================================================================
 *      ReadWriteLock class
 * ===========================================================================
 */

#if 0
#pragma mark -
#pragma mark ReadWriteLock
#endif

/*
 * Add a reader.  Readers are nice.  They share.
 */
void ReadWriteLock::lockForRead()
{
    mLock.lock();
    while (mNumWriters > 0) {
        LOG(LOG_DEBUG, "thread", "+++ lockForRead: waiting\n");
        mReadWaiter.wait(mLock);
    }
    assert(mNumWriters == 0);
    mNumReaders++;
#if defined(PRINT_RENDER_TIMES)
    if (mNumReaders == 1)
        mDebugTimer.start();
#endif
    mLock.unlock();
}

/*
 * Try to add a reader.  If it doesn't work right away, return "false".
 */
bool ReadWriteLock::tryLockForRead()
{
    mLock.lock();
    if (mNumWriters > 0) {
        mLock.unlock();
        return false;
    }
    assert(mNumWriters == 0);
    mNumReaders++;
#if defined(PRINT_RENDER_TIMES)
    if (mNumReaders == 1)
        mDebugTimer.start();
#endif
    mLock.unlock();
    return true;
}

/*
 * Remove a reader.
 */
void ReadWriteLock::unlockForRead()
{
    mLock.lock();
    if (mNumReaders == 0) {
        mLock.unlock();
        LOG(LOG_WARN, "thread",
            "WARNING: unlockForRead requested, but not locked\n");
        return;
    }
    assert(mNumReaders > 0);
    assert(mNumWriters == 0);
    mNumReaders--;
    if (mNumReaders == 0) {           // last reader?
#if defined(PRINT_RENDER_TIMES)
        mDebugTimer.stop();
        printf(" rdlk held %.3f msec\n",
            (double) mDebugTimer.durationUsecs() / 1000.0);
#endif
        //printf("+++ signaling writers (if any)\n");
        mWriteWaiter.signal();      // wake one writer (if any)
    }
    mLock.unlock();
}

/*
 * Add a writer.  This requires exclusive access to the object.
 */
void ReadWriteLock::lockForWrite()
{
    mLock.lock();
    while (mNumReaders > 0 || mNumWriters > 0) {
        LOG(LOG_DEBUG, "thread", "+++ lockForWrite: waiting\n");
        mWriteWaiter.wait(mLock);
    }
    assert(mNumReaders == 0);
    assert(mNumWriters == 0);
    mNumWriters++;
#if defined(PRINT_RENDER_TIMES)
    mDebugTimer.start();
#endif
    mLock.unlock();
}

/*
 * Try to add a writer.  If it doesn't work right away, return "false".
 */
bool ReadWriteLock::tryLockForWrite()
{
    mLock.lock();
    if (mNumReaders > 0 || mNumWriters > 0) {
        mLock.unlock();
        return false;
    }
    assert(mNumReaders == 0);
    assert(mNumWriters == 0);
    mNumWriters++;
#if defined(PRINT_RENDER_TIMES)
    mDebugTimer.start();
#endif
    mLock.unlock();
    return true;
}

/*
 * Remove a writer.
 */
void ReadWriteLock::unlockForWrite()
{
    mLock.lock();
    if (mNumWriters == 0) {
        mLock.unlock();
        LOG(LOG_WARN, "thread",
            "WARNING: unlockForWrite requested, but not locked\n");
        return;
    }
    assert(mNumWriters == 1);
    mNumWriters--;
#if defined(PRINT_RENDER_TIMES)
    mDebugTimer.stop();
    //printf(" wrlk held %.3f msec\n",
    //    (double) mDebugTimer.durationUsecs() / 1000.0);
#endif
    mWriteWaiter.signal();         // should other writers get first dibs?
    //printf("+++ signaling readers (if any)\n");
    mReadWaiter.broadcast();        // wake all readers (if any)
    mLock.unlock();
}

// ----------------------------------------------------------------------------

#if 0
@@ -1027,6 +886,8 @@ status_t Thread::run(const char* name, int32_t priority, size_t stack)
    // hold a strong reference on ourself
    mHoldSelf = this;

    mRunning = true;

    bool res;
    if (mCanCallJava) {
        res = createThreadEtc(_threadLoop,
@@ -1040,14 +901,16 @@ status_t Thread::run(const char* name, int32_t priority, size_t stack)
        mStatus = UNKNOWN_ERROR;   // something happened!
        mRunning = false;
        mThread = thread_id_t(-1);
    }
        mHoldSelf.clear();  // "this" may have gone away after this.

    if (mStatus < 0) {
        // something happened, don't leak
        mHoldSelf.clear();
        return UNKNOWN_ERROR;
    }
    
    return mStatus;
    // Do not refer to mStatus here: The thread is already running (may, in fact
    // already have exited with a valid mStatus result). The NO_ERROR indication
    // here merely indicates successfully starting the thread and does not
    // imply successful termination/execution.
    return NO_ERROR;
}

int Thread::_threadLoop(void* user)
@@ -1057,20 +920,32 @@ int Thread::_threadLoop(void* user)
    wp<Thread> weak(strong);
    self->mHoldSelf.clear();

    // we're about to run...
    bool first = true;

    do {
        bool result;
        if (first) {
            first = false;
            self->mStatus = self->readyToRun();
    if (self->mStatus!=NO_ERROR || self->mExitPending) {
        // pretend the thread never started...
        self->mExitPending = false;
        self->mRunning = false;
        return 0;
            result = (self->mStatus == NO_ERROR);

            if (result && !self->mExitPending) {
                // Binder threads (and maybe others) rely on threadLoop
                // running at least once after a successful ::readyToRun()
                // (unless, of course, the thread has already been asked to exit
                // at that point).
                // This is because threads are essentially used like this:
                //   (new ThreadSubclass())->run();
                // The caller therefore does not retain a strong reference to
                // the thread and the thread would simply disappear after the
                // successful ::readyToRun() call instead of entering the
                // threadLoop at least once.
                result = self->threadLoop();
            }
        } else {
            result = self->threadLoop();
        }

    // thread is running now
    self->mRunning = true;

    do {
        bool result = self->threadLoop();
        if (result == false || self->mExitPending) {
            self->mExitPending = true;
            self->mLock.lock();
@@ -1097,13 +972,12 @@ void Thread::requestExit()

status_t Thread::requestExitAndWait()
{
    if (mStatus == OK) {

    if (mThread == getThreadId()) {
        LOGW(
        "Thread (this=%p): don't call waitForExit() from this "
        "Thread object's thread. It's a guaranteed deadlock!",
        this);

        return WOULD_BLOCK;
    }
    
@@ -1114,7 +988,7 @@ status_t Thread::requestExitAndWait()
        mThreadExitedCondition.wait(mLock);
    }
    mExitPending = false;
    }

    return mStatus;
}