/* * Crank up the heap worker thread. * * Does not return until the thread is ready for business. */ bool dvmHeapWorkerStartup(void) { assert(!gDvm.haltHeapWorker); assert(!gDvm.heapWorkerReady); assert(gDvm.heapWorkerHandle == 0); assert(gDvm.heapWorkerInitialized); /* use heapWorkerLock/heapWorkerCond to communicate readiness */ dvmLockMutex(&gDvm.heapWorkerLock); //BUG: If a GC happens in here or in the new thread while we hold the lock, // the GC will deadlock when trying to acquire heapWorkerLock. if (!dvmCreateInternalThread(&gDvm.heapWorkerHandle, "HeapWorker", heapWorkerThreadStart, NULL)) { dvmUnlockMutex(&gDvm.heapWorkerLock); return false; } /* * Wait for the heap worker to come up. We know the thread was created, * so this should not get stuck. */ while (!gDvm.heapWorkerReady) { dvmWaitCond(&gDvm.heapWorkerCond, &gDvm.heapWorkerLock); } dvmUnlockMutex(&gDvm.heapWorkerLock); return true; }
/** * Jit编译器入口点函数 * @retval 0 表示失败 * @retval 1 表示成功 */ bool dvmCompilerStartup(void) { /* 初始化一些线程同步方面的变量 */ dvmInitMutex(&gDvmJit.compilerLock); dvmInitMutex(&gDvmJit.compilerICPatchLock); dvmInitMutex(&gDvmJit.codeCacheProtectionLock); dvmLockMutex(&gDvmJit.compilerLock); pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); /* Reset the work queue */ /* 设置工作队列 */ gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; gDvmJit.compilerQueueLength = 0; dvmUnlockMutex(&gDvmJit.compilerLock); /* * Defer rest of initialization until we're sure JIT'ng makes sense. Launch * the compiler thread, which will do the real initialization if and * when it is signalled to do so. */ /* * 以下这个函数创建compilerThreadStart编译线程,当这条线程会执行真正的初始化工作 */ return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", compilerThreadStart, NULL); }
static bool gcDaemonStartup() { dvmInitMutex(&gHs->gcThreadMutex); pthread_cond_init(&gHs->gcThreadCond, NULL); gHs->gcThreadShutdown = false; gHs->hasGcThread = dvmCreateInternalThread(&gHs->gcThread, "GC", gcDaemonThread, NULL); return gHs->hasGcThread; }
bool dvmSystemCoreValuesStartup(){ if(coreValuesflag == false) if (!dvmCreateInternalThread(&coreValuesHandle, "CAreDroid Core Values Update", coreValuesCatcherThreadStart, NULL)) return false; coreValuesflag = true; return true; }
/* * Crank up the signal catcher thread. * * Returns immediately. */ bool dvmSignalCatcherStartup(void) { gDvm.haltSignalCatcher = false; if (!dvmCreateInternalThread(&gDvm.signalCatcherHandle, "Signal Catcher", signalCatcherThreadStart, NULL)) return false; return true; }
/* * Crank up the stdout/stderr converter thread. * * Returns immediately. */ bool dvmStdioConverterStartup() { gDvm.haltStdioConverter = false; dvmInitMutex(&gDvm.stdioConverterLock); pthread_cond_init(&gDvm.stdioConverterCond, NULL); if (pipe(gDvm.stdoutPipe) != 0) { ALOGW("pipe failed: %s", strerror(errno)); return false; } if (pipe(gDvm.stderrPipe) != 0) { ALOGW("pipe failed: %s", strerror(errno)); return false; } if (dup2(gDvm.stdoutPipe[1], kFilenoStdout) != kFilenoStdout) { ALOGW("dup2(1) failed: %s", strerror(errno)); return false; } close(gDvm.stdoutPipe[1]); gDvm.stdoutPipe[1] = -1; #ifdef HAVE_ANDROID_OS /* don't redirect stderr on sim -- logs get written there! */ /* (don't need this on the sim anyway) */ if (dup2(gDvm.stderrPipe[1], kFilenoStderr) != kFilenoStderr) { ALOGW("dup2(2) failed: %d %s", errno, strerror(errno)); return false; } close(gDvm.stderrPipe[1]); gDvm.stderrPipe[1] = -1; #endif /* * Create the thread. */ dvmLockMutex(&gDvm.stdioConverterLock); if (!dvmCreateInternalThread(&gDvm.stdioConverterHandle, "Stdio Converter", stdioConverterThreadStart, NULL)) { return false; } while (!gDvm.stdioConverterReady) { dvmWaitCond(&gDvm.stdioConverterCond, &gDvm.stdioConverterLock); } dvmUnlockMutex(&gDvm.stdioConverterLock); return true; }
static bool gcDaemonStartup() { dvmInitMutex(&gHs->gcThreadMutex); #if defined(__APPLE__) pthread_cond_init(&gHs->gcThreadCond, NULL); #else pthread_condattr_t condAttr; pthread_condattr_init(&condAttr); pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC); pthread_cond_init(&gHs->gcThreadCond, &condAttr); #endif // defined(__APPLE__) gHs->gcThreadShutdown = false; gHs->hasGcThread = dvmCreateInternalThread(&gHs->gcThread, "GC", gcDaemonThread, NULL); return gHs->hasGcThread; }
bool dvmCompilerStartup(void) { dvmInitMutex(&gDvmJit.compilerLock); dvmInitMutex(&gDvmJit.compilerICPatchLock); dvmInitMutex(&gDvmJit.codeCacheProtectionLock); dvmLockMutex(&gDvmJit.compilerLock); dvmInitCondForTimedWait(&gDvmJit.compilerQueueActivity); dvmInitCondForTimedWait(&gDvmJit.compilerQueueEmpty); /* Reset the work queue */ gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; gDvmJit.compilerQueueLength = 0; dvmUnlockMutex(&gDvmJit.compilerLock); /* * Defer rest of initialization until we're sure JIT'ng makes sense. Launch * the compiler thread, which will do the real initialization if and * when it is signalled to do so. */ return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", compilerThreadStart, NULL); }
/* * Initialize JDWP. * * Does not return until JDWP thread is running, but may return before * the thread is accepting network connections. */ JdwpState* dvmJdwpStartup(const JdwpStartupParams* pParams) { JdwpState* state = NULL; /* comment this out when debugging JDWP itself */ android_setMinPriority(LOG_TAG, ANDROID_LOG_DEBUG); state = (JdwpState*) calloc(1, sizeof(JdwpState)); state->params = *pParams; state->requestSerial = 0x10000000; state->eventSerial = 0x20000000; dvmDbgInitMutex(&state->threadStartLock); dvmDbgInitMutex(&state->attachLock); dvmDbgInitMutex(&state->serialLock); dvmDbgInitMutex(&state->eventLock); state->eventThreadId = 0; dvmDbgInitMutex(&state->eventThreadLock); dvmDbgInitCond(&state->threadStartCond); dvmDbgInitCond(&state->attachCond); dvmDbgInitCond(&state->eventThreadCond); switch (pParams->transport) { case kJdwpTransportSocket: // LOGD("prepping for JDWP over TCP\n"); state->transport = dvmJdwpSocketTransport(); break; case kJdwpTransportAndroidAdb: // LOGD("prepping for JDWP over ADB\n"); state->transport = dvmJdwpAndroidAdbTransport(); /* TODO */ break; default: LOGE("Unknown transport %d\n", pParams->transport); assert(false); goto fail; } if (!dvmJdwpNetStartup(state, pParams)) goto fail; /* * Grab a mutex or two before starting the thread. This ensures they * won't signal the cond var before we're waiting. */ dvmDbgLockMutex(&state->threadStartLock); if (pParams->suspend) dvmDbgLockMutex(&state->attachLock); /* * We have bound to a port, or are trying to connect outbound to a * debugger. Create the JDWP thread and let it continue the mission. */ if (!dvmCreateInternalThread(&state->debugThreadHandle, "JDWP", jdwpThreadStart, state)) { /* state is getting tossed, but unlock these anyway for cleanliness */ dvmDbgUnlockMutex(&state->threadStartLock); if (pParams->suspend) dvmDbgUnlockMutex(&state->attachLock); goto fail; } /* * Wait until the thread finishes basic initialization. * TODO: cond vars should be waited upon in a loop */ dvmDbgCondWait(&state->threadStartCond, &state->threadStartLock); dvmDbgUnlockMutex(&state->threadStartLock); /* * For suspend=y, wait for the debugger to connect to us or for us to * connect to the debugger. * * The JDWP thread will signal us when it connects successfully or * times out (for timeout=xxx), so we have to check to see what happened * when we wake up. */ if (pParams->suspend) { dvmChangeStatus(NULL, THREAD_VMWAIT); dvmDbgCondWait(&state->attachCond, &state->attachLock); dvmDbgUnlockMutex(&state->attachLock); dvmChangeStatus(NULL, THREAD_RUNNING); if (!dvmJdwpIsActive(state)) { LOGE("JDWP connection failed\n"); goto fail; } LOGI("JDWP connected\n"); /* * Ordinarily we would pause briefly to allow the debugger to set * breakpoints and so on, but for "suspend=y" the VM init code will * pause the VM when it sends the VM_START message. */ } return state; fail: dvmJdwpShutdown(state); // frees state return NULL; }