static jboolean installSignals(Env* env) { #if defined(DARWIN) // On Darwin SIGBUS is generated when dereferencing NULL pointers if (installSignalHandlerIfNeeded(SIGBUS, create_sigaction(&signalHandler_npe_so_nochaining), NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); return FALSE; } #endif if (installSignalHandlerIfNeeded(SIGSEGV, create_sigaction(&signalHandler_npe_so_nochaining), NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); return FALSE; } if (installSignalHandlerIfNeeded(DUMP_THREAD_STACK_TRACE_SIGNAL, create_sigaction(&signalHandler_dump_thread), NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); return FALSE; } int err; if ((err = pthread_sigmask(0, NULL, &env->currentThread->signalMask)) != 0) { rvmThrowInternalErrorErrno(env, err); rvmTearDownSignals(env); return FALSE; } return TRUE; }
static jboolean reinstallSavedSignals(Env* env, SavedSignals* savedSignals) { if (installSignalHandlerIfNeeded(DUMP_THREAD_STACK_TRACE_SIGNAL, create_sigaction(&signalHandler_dump_thread), NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); return FALSE; } if (installSignalHandlerIfNeeded(BLOCKED_THREAD_SIGNAL, savedSignals->blockedThreadSignal, NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); return FALSE; } return TRUE; }
/** * Associates the specified Env* with the current thread. */ static void setThreadEnv(Env* env) { int err = pthread_setspecific(tlsEnvKey, env); assert(err == 0); if (err != 0) { rvmThrowInternalErrorErrno(env, err); } }
static jboolean installChainingSignals(Env* env) { #if defined(DARWIN) // On Darwin SIGBUS is generated when dereferencing NULL pointers if (installSignalHandlerIfNeeded(SIGBUS, create_sigaction(&signalHandler_npe_so_chaining), &sigbusFallback) != 0) { rvmThrowInternalErrorErrno(env, errno); return FALSE; } #endif if (installSignalHandlerIfNeeded(SIGSEGV, create_sigaction(&signalHandler_npe_so_chaining), &sigsegvFallback) != 0) { rvmThrowInternalErrorErrno(env, errno); return FALSE; } return TRUE; }
jboolean rvmInstallThreadSignalMask(Env* env) { int err; if ((err = pthread_sigmask(0, NULL, &env->currentThread->signalMask)) != 0) { rvmThrowInternalErrorErrno(env, err); return FALSE; } return TRUE; }
jlong rvmStartThread(Env* env, JavaThread* threadObj) { Env* newEnv = rvmCreateEnv(env->vm); if (!newEnv) { rvmThrowOutOfMemoryError(env); // rvmCreateEnv() doesn't throw OutOfMemoryError if allocation fails return 0; } rvmLockThreadsList(); if (threadObj->threadPtr != 0) { rvmThrowIllegalStateException(env, "thread has already been started"); rvmUnlockThreadsList(); return 0; } Thread* thread = allocThread(env); if (!thread) { rvmUnlockThreadsList(); return 0; } size_t stackSize = (size_t) threadObj->stackSize; if (stackSize == 0) { stackSize = THREAD_DEFAULT_STACK_SIZE; } else if (stackSize < THREAD_MIN_STACK_SIZE) { stackSize = THREAD_MIN_STACK_SIZE; } stackSize += THREAD_SIGNAL_STACK_SIZE; stackSize = (stackSize + THREAD_STACK_SIZE_MULTIPLE - 1) & ~(THREAD_STACK_SIZE_MULTIPLE - 1); pthread_attr_t threadAttr; pthread_attr_init(&threadAttr); pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&threadAttr, stackSize); pthread_attr_setguardsize(&threadAttr, THREAD_STACK_GUARD_SIZE); ThreadEntryPointArgs args = {0}; args.env = newEnv; args.thread = thread; args.threadObj = threadObj; int err = 0; if ((err = pthread_create(&thread->pThread, &threadAttr, startThreadEntryPoint, &args)) != 0) { rvmUnlockThreadsList(); rvmThrowInternalErrorErrno(env, err); return 0; } while (thread->status != THREAD_STARTING) { pthread_cond_wait(&threadStartCond, &threadsLock); } DL_PREPEND(threads, thread); pthread_cond_broadcast(&threadsChangedCond); thread->status = THREAD_VMWAIT; pthread_cond_broadcast(&threadStartCond); rvmUnlockThreadsList(); return PTR_TO_LONG(thread); }
static jboolean installSignalHandlers(Env* env) { struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO | SA_ONSTACK; sa.sa_sigaction = &signalHandler_npe_so; #if defined(DARWIN) // On Darwin SIGBUS is generated when dereferencing NULL pointers if (sigaction(SIGBUS, &sa, NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); rvmTearDownSignals(env); return FALSE; } #endif if (sigaction(SIGSEGV, &sa, NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); rvmTearDownSignals(env); return FALSE; } sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO | SA_ONSTACK; sa.sa_sigaction = &signalHandler_dump_thread; if (sigaction(DUMP_THREAD_STACK_TRACE_SIGNAL, &sa, NULL) != 0) { rvmThrowInternalErrorErrno(env, errno); rvmTearDownSignals(env); return FALSE; } int err; if ((err = pthread_sigmask(0, NULL, &env->currentThread->signalMask)) != 0) { rvmThrowInternalErrorErrno(env, err); rvmTearDownSignals(env); return FALSE; } return TRUE; }
static jboolean initThread(Env* env, Thread* thread, JavaThread* threadObj) { // NOTE: threadsLock must be held int err = 0; pthread_cond_init(&thread->waitCond, NULL); if ((err = rvmInitMutex(&thread->waitMutex)) != 0) { rvmThrowInternalErrorErrno(env, err); return FALSE; } thread->threadId = nextThreadId++; thread->threadObj = threadObj; threadObj->threadPtr = PTR_TO_LONG(thread); env->currentThread = thread; env->attachCount = 1; return TRUE; }