Loading include/utils/threads.h +0 −35 Original line number Diff line number Diff line Loading @@ -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! */ Loading libs/utils/CallStack.cpp +19 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; } }; Loading Loading @@ -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"); Loading libs/utils/ResourceTypes.cpp +8 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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++; } Loading libs/utils/String16.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading libs/utils/Threads.cpp +50 −176 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ // #define LOG_NDEBUG 0 #define LOG_TAG "libutils.threads" #include <utils/threads.h> Loading Loading @@ -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 Loading Loading @@ -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, Loading @@ -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) Loading @@ -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(); Loading @@ -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; } Loading @@ -1114,7 +988,7 @@ status_t Thread::requestExitAndWait() mThreadExitedCondition.wait(mLock); } mExitPending = false; } return mStatus; } Loading Loading
include/utils/threads.h +0 −35 Original line number Diff line number Diff line Loading @@ -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! */ Loading
libs/utils/CallStack.cpp +19 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; } }; Loading Loading @@ -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"); Loading
libs/utils/ResourceTypes.cpp +8 −6 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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++; } Loading
libs/utils/String16.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
libs/utils/Threads.cpp +50 −176 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ // #define LOG_NDEBUG 0 #define LOG_TAG "libutils.threads" #include <utils/threads.h> Loading Loading @@ -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 Loading Loading @@ -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, Loading @@ -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) Loading @@ -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(); Loading @@ -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; } Loading @@ -1114,7 +988,7 @@ status_t Thread::requestExitAndWait() mThreadExitedCondition.wait(mLock); } mExitPending = false; } return mStatus; } Loading