Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
void Java_java_lang_Thread_internalSetPriority(Env* env, Class* cls, JavaThread* threadObj, jint priority) {
    rvmLockThreadsList();
    Thread* thread = (Thread*) LONG_TO_PTR(threadObj->threadPtr);
    if (thread) {
        rvmChangeThreadPriority(env, thread, priority);
    }
    rvmUnlockThreadsList();
}
Ejemplo n.º 3
0
void Java_java_lang_Thread_internalInterrupt(Env* env, Class* cls, JavaThread* threadObj) {
    rvmLockThreadsList();
    Thread* thread = (Thread*) LONG_TO_PTR(threadObj->threadPtr);
    if (thread) {
        rvmThreadInterrupt(env, thread);
    }
    rvmUnlockThreadsList();
}
Ejemplo n.º 4
0
void Java_java_lang_Thread_internalSetName(Env* env, Class* cls, JavaThread* threadObj, Object* threadName) {
    rvmLockThreadsList();
    Thread* thread = (Thread*) LONG_TO_PTR(threadObj->threadPtr);
    if (thread) {
        rvmThreadNameChanged(env, thread);
    }
    rvmUnlockThreadsList();
}
Ejemplo n.º 5
0
jint Java_java_lang_Thread_internalGetState(Env* env, Class* cls, JavaThread* threadObj) {
    rvmLockThreadsList();
    Thread* thread = (Thread*) LONG_TO_PTR(threadObj->threadPtr);
    jint status = THREAD_ZOMBIE; // If thread==NULL we assume the thread has been finished
    if (thread) {
        status = thread->status;
    }
    rvmUnlockThreadsList();
    return status;
}
Ejemplo n.º 6
0
jboolean Java_java_lang_Thread_internalHoldsLock(Env* env, Class* cls, Object* obj) {
    if (!obj) {
        rvmThrowNullPointerException(env);
        return FALSE;
    }
    rvmLockThreadsList();
    jboolean result = rvmHoldsLock(env, env->currentThread, obj);
    rvmUnlockThreadsList();
    return result;
}
Ejemplo n.º 7
0
jboolean Java_java_lang_Thread_internalIsInterrupted(Env* env, Class* cls, JavaThread* threadObj) {
    rvmLockThreadsList();
    Thread* thread = (Thread*) LONG_TO_PTR(threadObj->threadPtr);
    jboolean interrupted = FALSE;
    if (thread) {
        interrupted = thread->interrupted;
    }
    rvmUnlockThreadsList();
    return interrupted;
}
Ejemplo n.º 8
0
static void* startThreadEntryPoint(void* _args) {
    ThreadEntryPointArgs* args = (ThreadEntryPointArgs*) _args;
    Env* env = args->env;
    Thread* thread = args->thread;
    JavaThread* threadObj = args->threadObj;

    rvmLockThreadsList();
    jboolean failure = TRUE;

    setThreadEnv(env);
    if (!rvmExceptionOccurred(env)) {
        if (initThread(env, thread, threadObj)) {
            if (rvmSetupSignals(env)) {
                failure = FALSE;
                thread->stackAddr = getStackAddress();
            }
        }
    }
    
    thread->status = THREAD_STARTING;
    pthread_cond_broadcast(&threadStartCond);
    while (thread->status != THREAD_VMWAIT) {
        pthread_cond_wait(&threadStartCond, &threadsLock);
    }
    rvmUnlockThreadsList();

    if (!failure) {
        rvmChangeThreadStatus(env, thread, THREAD_RUNNING);

        rvmChangeThreadPriority(env, thread, thread->threadObj->priority);

        Method* run = rvmGetInstanceMethod2(env, java_lang_Thread, "run", "()V");
        if (run) {
            jvalue emptyArgs[0];
            rvmCallVoidInstanceMethodA(env, (Object*) threadObj, run, emptyArgs);
        }
    }

    detachThread(env, TRUE);

    return NULL;
}
Ejemplo n.º 9
0
static jint detachThread(Env* env, jboolean ignoreAttachCount) {
    env->attachCount--;
    if (!ignoreAttachCount && env->attachCount > 0) {
        return JNI_OK;
    }

    if (env->gatewayFrames) {
        rvmAbort("Cannot detach thread when there are non native frames on the call stack");
    }

    // TODO: Release all monitors still held by this thread (should only be monitors acquired from JNI code)

    Thread* thread = env->currentThread;

    if (rvmExceptionOccurred(env)) {
        threadExitUncaughtException(env, thread);
    }

    if (thread->threadObj->group) {
        rvmCallVoidInstanceMethod(env, thread->threadObj->group, removeThreadMethod, thread->threadObj);
        rvmExceptionClear(env);
    }

    // Set threadPtr to null
    rvmAtomicStoreLong(&thread->threadObj->threadPtr, 0);

    // Notify anyone waiting on this thread (using Thread.join())
    rvmLockObject(env, thread->threadObj->lock);
    rvmObjectNotifyAll(env, thread->threadObj->lock);
    rvmUnlockObject(env, thread->threadObj->lock);

    rvmLockThreadsList();
    thread->status = THREAD_ZOMBIE;
    DL_DELETE(threads, thread);
    pthread_cond_broadcast(&threadsChangedCond);
    rvmTearDownSignals(env);
    env->currentThread = NULL;
    pthread_setspecific(tlsEnvKey, NULL);
    rvmUnlockThreadsList();

    return JNI_OK;
}
Ejemplo n.º 10
0
static jint attachThread(VM* vm, Env** envPtr, char* name, Object* group, jboolean daemon) {
    Env* env = *envPtr; // env is NULL if rvmAttachCurrentThread() was called. If non NULL rvmInitThreads() was called.
    if (!env) {
        // If the thread was already attached there's an Env* associated with the thread.
        env = (Env*) pthread_getspecific(tlsEnvKey);
        if (env) {
            env->attachCount++;
            *envPtr = env;
            return JNI_OK;
        }
    }
    
    if (!env) {
        env = rvmCreateEnv(vm);
        if (!env) goto error;
    }

    setThreadEnv(env);
    if (rvmExceptionOccurred(env)) goto error;

    Thread* thread = allocThread(env);
    if (!thread) goto error;
    thread->stackAddr = getStackAddress();
    thread->pThread = pthread_self();
    env->currentThread = thread;
    rvmChangeThreadStatus(env, thread, THREAD_RUNNING);
    
    JavaThread* threadObj = (JavaThread*) rvmAllocateObject(env, java_lang_Thread);
    if (!threadObj) goto error;

    rvmLockThreadsList();
    if (!initThread(env, thread, threadObj)) {
        rvmUnlockThreadsList();
        goto error;
    }
    if (!rvmSetupSignals(env)) {
        rvmUnlockThreadsList();
        goto error;
    }
    DL_PREPEND(threads, thread);
    pthread_cond_broadcast(&threadsChangedCond);
    rvmUnlockThreadsList();

    Object* threadName = NULL;
    if (name) {
        threadName = rvmNewStringUTF(env, name, -1);
        if (!threadName) goto error_remove;
    }

    Method* threadConstructor = rvmGetInstanceMethod2(env, java_lang_Thread, "<init>", "(JLjava/lang/String;Ljava/lang/ThreadGroup;Z)V");
    if (!threadConstructor) goto error_remove;

    rvmCallNonvirtualVoidInstanceMethod(env, (Object*) threadObj, threadConstructor, PTR_TO_LONG(thread), threadName, group, daemon);
    if (rvmExceptionOccurred(env)) goto error_remove;

    *envPtr = env;

    return JNI_OK;

error_remove:
    rvmLockThreadsList();
    DL_DELETE(threads, thread);
    pthread_cond_broadcast(&threadsChangedCond);
    rvmTearDownSignals(env);
    rvmUnlockThreadsList();
error:
    if (env) env->currentThread = NULL;
    clearThreadEnv();
    return JNI_ERR;
}