summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:35 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:35 -0800
commit9adf84a4b6735354893ff1e57c129f66d97d75ee (patch)
tree6fad0d5c1e6ba13f6ec539e4dec71e2c5f57ed39 /libs
parentedbf3b6af777b721cd2a1ef461947e51e88241e1 (diff)
downloadframeworks_native-9adf84a4b6735354893ff1e57c129f66d97d75ee.zip
frameworks_native-9adf84a4b6735354893ff1e57c129f66d97d75ee.tar.gz
frameworks_native-9adf84a4b6735354893ff1e57c129f66d97d75ee.tar.bz2
auto import from //depot/cupcake/@136594
Diffstat (limited to 'libs')
-rw-r--r--libs/utils/CallStack.cpp25
-rw-r--r--libs/utils/ResourceTypes.cpp14
-rw-r--r--libs/utils/String16.cpp2
-rw-r--r--libs/utils/Threads.cpp226
4 files changed, 78 insertions, 189 deletions
diff --git a/libs/utils/CallStack.cpp b/libs/utils/CallStack.cpp
index 26fb22a..2fdaa71 100644
--- a/libs/utils/CallStack.cpp
+++ b/libs/utils/CallStack.cpp
@@ -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");
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 71e7cd7..2ad3bfe 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -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,13 +3152,13 @@ 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++;
}
- //printf("Looking for: %s\n", String8(start, pos-start).string());
+ //printf("Looking for: %s\n", String8(start, pos-start).string());
const bag_entry* bagi = bag;
- ssize_t i;
+ ssize_t i;
for (i=0; i<cnt; i++, bagi++) {
if (!Res_INTERNALID(bagi->map.name.ident)) {
//printf("Trying attr #%08x\n", bagi->map.name.ident);
@@ -3184,7 +3186,7 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
}
unlockBag(bag);
if (!failed) {
- //printf("Final flag value: 0x%lx\n", outValue->data);
+ //printf("Final flag value: 0x%lx\n", outValue->data);
return true;
}
}
@@ -3192,7 +3194,7 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
if (fromAccessor) {
if (accessor->getAttributeFlags(attrID, s, len, outValue)) {
- //printf("Final flag value: 0x%lx\n", outValue->data);
+ //printf("Final flag value: 0x%lx\n", outValue->data);
return true;
}
}
diff --git a/libs/utils/String16.cpp b/libs/utils/String16.cpp
index 1f81cad..ae0ae1e 100644
--- a/libs/utils/String16.cpp
+++ b/libs/utils/String16.cpp
@@ -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;
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 5f407a9..9287c0b 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -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.
+
+ return UNKNOWN_ERROR;
}
- if (mStatus < 0) {
- // something happened, don't leak
- mHoldSelf.clear();
- }
-
- 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...
- self->mStatus = self->readyToRun();
- if (self->mStatus!=NO_ERROR || self->mExitPending) {
- // pretend the thread never started...
- self->mExitPending = false;
- self->mRunning = false;
- return 0;
- }
-
- // thread is running now
- self->mRunning = true;
+ bool first = true;
do {
- bool result = self->threadLoop();
+ bool result;
+ if (first) {
+ first = false;
+ self->mStatus = self->readyToRun();
+ 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();
+ }
+
if (result == false || self->mExitPending) {
self->mExitPending = true;
self->mLock.lock();
@@ -1097,24 +972,23 @@ 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;
- }
-
- requestExit();
+ if (mThread == getThreadId()) {
+ LOGW(
+ "Thread (this=%p): don't call waitForExit() from this "
+ "Thread object's thread. It's a guaranteed deadlock!",
+ this);
- Mutex::Autolock _l(mLock);
- while (mRunning == true) {
- mThreadExitedCondition.wait(mLock);
- }
- mExitPending = false;
+ return WOULD_BLOCK;
}
+
+ requestExit();
+
+ Mutex::Autolock _l(mLock);
+ while (mRunning == true) {
+ mThreadExitedCondition.wait(mLock);
+ }
+ mExitPending = false;
+
return mStatus;
}