/* Basically we need to cleanup any state kept around for this thread and let * the other side know the thread is exiting if needed. */ void offThreadExited(Thread* self) { u4 threadId = self->threadId; /* Inform the other endpoint that we're exiting if started locally. We can * avoid this if the other endpoint doesn't even know about this thread. */ if((threadId & 0x8000) == (gDvm.isServer ? 0x8000 : 0)) { if(!self->offLocalOnly) { offWriteU1(self, OFF_ACTION_DEATH); offSyncPush(); ALOGI("THREAD %d WAITING FOR SIGNOFF", threadId); offThreadWaitForResume(self); ALOGI("THREAD %d SIGNING OFF", threadId); } } /* Remove the thread from the thread table. */ if(gDvm.offThreadTable) { dvmHashTableLock(gDvm.offThreadTable); dvmHashTableRemove(gDvm.offThreadTable, threadId, self); dvmHashTableUnlock(gDvm.offThreadTable); } offFlushStream(self); if((threadId & 0x8000) == (gDvm.isServer ? 0x8000 : 0)) { dvmClearBit(gDvm.threadIdMap, ((threadId & 0x7FFF) >> 1) - 1); } else {
int hprofShutdown_Stack() { HashIter iter; /* This will be called when a GC has completed. */ for (dvmHashIterBegin(gStackTraceHashTable, &iter); !dvmHashIterDone(&iter); dvmHashIterNext(&iter)) { StackTraceEntry *stackTraceEntry; /* * If the 'live' bit is 0, the trace is not in use by any current * heap object and may be destroyed. */ stackTraceEntry = (StackTraceEntry *) dvmHashIterData(&iter); if (!stackTraceEntry->live) { dvmHashTableRemove(gStackTraceHashTable, computeStackTraceHash(stackTraceEntry), stackTraceEntry); free(stackTraceEntry); } } return 0; }
static StringObject* lookupInternedString(StringObject* strObj, bool isLiteral) { StringObject* found; assert(strObj != NULL); u4 key = dvmComputeStringHash(strObj); dvmLockMutex(&gDvm.internLock); if (isLiteral) { /* * Check the literal table for a match. */ StringObject* literal = lookupString(gDvm.literalStrings, key, strObj); if (literal != NULL) { /* * A match was found in the literal table, the easy case. */ found = literal; } else { /* * There is no match in the literal table, check the * interned string table. */ StringObject* interned = lookupString(gDvm.internedStrings, key, strObj); if (interned != NULL) { /* * A match was found in the interned table. Move the * matching string to the literal table. */ dvmHashTableRemove(gDvm.internedStrings, key, interned); found = insertString(gDvm.literalStrings, key, interned); assert(found == interned); } else { /* * No match in the literal table or the interned * table. Insert into the literal table. */ found = insertString(gDvm.literalStrings, key, strObj); assert(found == strObj); } } } else { /* * Check the literal table for a match. */ found = lookupString(gDvm.literalStrings, key, strObj); if (found == NULL) { /* * No match was found in the literal table. Insert into * the intern table if it does not already exist. */ found = insertString(gDvm.internedStrings, key, strObj); } } assert(found != NULL); dvmUnlockMutex(&gDvm.internLock); return found; }
/* * private static void closeDexFile(int cookie) * * Release resources associated with a user-loaded DEX file. */ static void Dalvik_dalvik_system_DexFile_closeDexFile(const u4* args, JValue* pResult) { int cookie = args[0]; DexOrJar* pDexOrJar = (DexOrJar*) cookie; if (pDexOrJar == NULL) RETURN_VOID(); LOGV("Closing DEX file %p (%s)\n", pDexOrJar, pDexOrJar->fileName); if (!validateCookie(cookie)) RETURN_VOID(); /* * We can't just free arbitrary DEX files because they have bits and * pieces of loaded classes. The only exception to this rule is if * they were never used to load classes. * * If we can't free them here, dvmInternalNativeShutdown() will free * them when the VM shuts down. */ if (pDexOrJar->okayToFree) { u4 hash = dvmComputeUtf8Hash(pDexOrJar->fileName); dvmHashTableLock(gDvm.userDexFiles); if (!dvmHashTableRemove(gDvm.userDexFiles, hash, pDexOrJar)) { LOGW("WARNING: could not remove '%s' from DEX hash table\n", pDexOrJar->fileName); } dvmHashTableUnlock(gDvm.userDexFiles); LOGV("+++ freeing DexFile '%s' resources\n", pDexOrJar->fileName); dvmFreeDexOrJar(pDexOrJar); } else { LOGV("+++ NOT freeing DexFile '%s' resources\n", pDexOrJar->fileName); } RETURN_VOID(); }
/* * Some quick hash table tests. */ bool dvmTestHash() { HashTable* pTab; char tmpStr[64]; const char* str; u4 hash; int i; ALOGV("TestHash BEGIN"); pTab = dvmHashTableCreate(dvmHashSize(12), free); if (pTab == NULL) return false; dvmHashTableLock(pTab); /* add some entries */ for (i = 0; i < kNumTestEntries; i++) { sprintf(tmpStr, "entry %d", i); hash = dvmComputeUtf8Hash(tmpStr); dvmHashTableLookup(pTab, hash, strdup(tmpStr), (HashCompareFunc) strcmp, true); } dvmHashTableUnlock(pTab); /* make sure we can find all entries */ for (i = 0; i < kNumTestEntries; i++) { sprintf(tmpStr, "entry %d", i); hash = dvmComputeUtf8Hash(tmpStr); str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr, (HashCompareFunc) strcmp, false); if (str == NULL) { ALOGE("TestHash: failure: could not find '%s'", tmpStr); /* return false */ } } /* make sure it behaves correctly when entry not found and !doAdd */ sprintf(tmpStr, "entry %d", 17); hash = dvmComputeUtf8Hash(tmpStr); str = (const char*) dvmHashTableLookup(pTab, hash, tmpStr, (HashCompareFunc) strcmp, false); if (str == NULL) { /* good */ } else { ALOGE("TestHash found nonexistent string (improper add?)"); } dumpForeach(pTab); dumpIterator(pTab); /* make sure they all get freed */ dvmHashTableFree(pTab); /* * Round 2: verify probing & tombstones. */ pTab = dvmHashTableCreate(dvmHashSize(2), free); if (pTab == NULL) return false; hash = 0; /* two entries, same hash, different values */ const char* str1; str1 = (char*) dvmHashTableLookup(pTab, hash, strdup("one"), (HashCompareFunc) strcmp, true); assert(str1 != NULL); str = (const char*) dvmHashTableLookup(pTab, hash, strdup("two"), (HashCompareFunc) strcmp, true); /* remove the first one */ if (!dvmHashTableRemove(pTab, hash, (void*)str1)) ALOGE("TestHash failed to delete item"); else free((void*)str1); // "Remove" doesn't call the free func /* make sure iterator doesn't included deleted entries */ int count = 0; HashIter iter; for (dvmHashIterBegin(pTab, &iter); !dvmHashIterDone(&iter); dvmHashIterNext(&iter)) { count++; } if (count != 1) { ALOGE("TestHash wrong number of entries (%d)", count); } /* see if we can find them */ str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"one", (HashCompareFunc) strcmp,false); if (str != NULL) ALOGE("TestHash deleted entry has returned!"); str = (const char*) dvmHashTableLookup(pTab, hash, (void*)"two", (HashCompareFunc) strcmp,false); if (str == NULL) ALOGE("TestHash entry vanished"); /* force a table realloc to exercise tombstone removal */ for (i = 0; i < 20; i++) { sprintf(tmpStr, "entry %d", i); str = (const char*) dvmHashTableLookup(pTab, hash, strdup(tmpStr), (HashCompareFunc) strcmp, true); assert(str != NULL); } dvmHashTableFree(pTab); ALOGV("TestHash END"); return true; }