示例#1
0
jvmtiError JNICALL
jvmtiGetLocalLong(jvmtiEnv* env,
                  jthread thread,
                  jint depth,
                  jint slot,
                  jlong* value_ptr)
{
    TRACE("GetLocalLong called");
    SuspendEnabledChecker sec;
    /*
     * Check given env & current phase.
     */
    jvmtiPhase phases[] = {JVMTI_PHASE_LIVE};

    CHECK_EVERYTHING();

    CHECK_CAPABILITY(can_access_local_variables);

    // check error condition: JVMTI_ERROR_INVALID_THREAD
    // check error condition: JVMTI_ERROR_THREAD_NOT_ALIVE
    // check error condition: JVMTI_ERROR_ILLEGAL_ARGUMENT
    // check error condition: JVMTI_ERROR_NULL_POINTER
    jvmtiError err = GetLocal_checkArgs(env, &thread, depth, slot, value_ptr);
    if (err != JVMTI_ERROR_NONE)
        return err;

    bool thread_suspended = false;
    // Suspend thread before getting stacks
    vm_thread_t vm_thread;
    if (NULL != thread)
    {
        // Check that this thread is not current
        vm_thread = jthread_get_vm_thread_ptr_safe(thread);
        if (vm_thread != p_TLS_vmthread)
        {
            IDATA UNREF status = hythread_suspend_other((hythread_t)vm_thread);
            assert(TM_ERROR_NONE == status);
            thread_suspended = true;
        }
    }
    else
        vm_thread = p_TLS_vmthread;

    if (interpreter_enabled())
        // check error condition: JVMTI_ERROR_INVALID_SLOT
        // check error condition: JVMTI_ERROR_OPAQUE_FRAME
        // check error condition: JVMTI_ERROR_NO_MORE_FRAMES
        // TODO: check error condition: JVMTI_ERROR_TYPE_MISMATCH
        err = interpreter.interpreter_ti_getLocal64(env,
            vm_thread, depth, slot, value_ptr);
    else
    {
        GET_JIT_FRAME_CONTEXT;

        tmn_suspend_disable();
        OpenExeJpdaError result = jit->get_local_var(method, jfc, slot,
            VM_DATA_TYPE_INT64, value_ptr);
        si_free(si);
        tmn_suspend_enable();

        err = jvmti_translate_jit_error(result);
    }

    if (thread_suspended)
        hythread_resume((hythread_t)vm_thread);

    return err;
}
示例#2
0
/**
 * Used lockword
 * Thin monitor functions used java monitor.
 */
IDATA VMCALL hythread_unreserve_lock(hythread_thin_monitor_t *lockword_ptr) {
    U_32 lockword = *lockword_ptr;
    U_32 lockword_new;
    uint16 lock_id;
    hythread_t owner;
    IDATA status;
    I_32 append;

    // trylock used to prevent cyclic suspend deadlock
    // the java_monitor_enter calls safe_point between attempts.
    /*status = port_mutex_trylock(&TM_LOCK);
      if (status !=TM_ERROR_NONE) {
      return status;
      }*/
    
    if (IS_FAT_LOCK(lockword)) {
        return TM_ERROR_NONE;
    }
    lock_id = THREAD_ID(lockword);
    owner = hythread_get_thread(lock_id);
    CTRACE(("Unreserved other %d \n", ++unreserve_count/*, vm_get_object_class_name(lockword_ptr-1)*/));
    if (!IS_RESERVED(lockword) || IS_FAT_LOCK(lockword)) {
        // port_mutex_unlock(&TM_LOCK);
        return TM_ERROR_NONE;
    }
    // suspend owner 
    if (owner) {
        assert(owner);
        assert(hythread_get_id(owner) == lock_id);
        assert(owner != hythread_self());
        if(owner->state
                & (TM_THREAD_STATE_TERMINATED
                    | TM_THREAD_STATE_WAITING
                    | TM_THREAD_STATE_WAITING_INDEFINITELY
                    | TM_THREAD_STATE_WAITING_WITH_TIMEOUT
                    | TM_THREAD_STATE_SLEEPING
                    | TM_THREAD_STATE_PARKED
                    | TM_THREAD_STATE_SUSPENDED
                    | TM_THREAD_STATE_IN_MONITOR_WAIT))
        {
            append = 0;
        } else {
            append = RESERVED_BITMASK;
        }

        status=hythread_suspend_other(owner);
        if (status !=TM_ERROR_NONE) {
            return status;
        }
    } else {
        append = 0;
    }

    if(!tm_properties || !tm_properties->use_soft_unreservation) {
	    append = RESERVED_BITMASK;
    }

    // prepare new unreserved lockword and try to CAS it with old one.
    while (IS_RESERVED(lockword)) {
        assert(!IS_FAT_LOCK(lockword));
        CTRACE(("unreserving lock"));
        if (RECURSION(lockword) != 0) {
            lockword_new = (lockword | RESERVED_BITMASK);
            assert(RECURSION(lockword) > 0);
            assert(RECURSION(lockword_new) > 0);
            RECURSION_DEC(&lockword_new, lockword_new);
        } else {
            lockword_new = (lockword | append);
            lockword_new =  lockword_new & 0x0000ffff; 
        }
        if (lockword == apr_atomic_cas32 (((volatile apr_uint32_t*) lockword_ptr), 
                                          (apr_uint32_t) lockword_new, lockword)) {
            CTRACE(("unreserved lock"));
            break;
        }
        lockword = *lockword_ptr;
    }

    // resume owner
    if (owner) {
        hythread_yield_other(owner);
        hythread_resume(owner);
    }

    /* status = port_mutex_unlock(&TM_LOCK);*/

    // Gregory - This lock, right after it was unreserved, may be
    // inflated by another thread and therefore instead of recursion
    // count and reserved flag it will have the fat monitor ID. The
    // assertion !IS_RESERVED(lockword) fails in this case. So it is
    // necessary to check first that monitor is not fat.
    // To avoid race condition between checking two different
    // conditions inside of assert, the lockword contents has to be
    // loaded before checking.
//    lockword = *lockword_ptr;
//    assert(IS_FAT_LOCK(lockword) || !IS_RESERVED(lockword));
    return TM_ERROR_NONE;
}
示例#3
0
/**
 * General function to set value of local variable.
 * @param var_type  type of the local variable
 * @param p_value   pointer to the new variable value
 */
static jvmtiError set_local(jvmtiEnv* env,
                            jthread thread,
                            jint depth,
                            jint slot,
                            VM_Data_Type var_type,
                            void* p_value)
{
    SuspendEnabledChecker sec;
    /*
     * Check given env & current phase.
     */
    jvmtiPhase phases[] = {JVMTI_PHASE_LIVE};

    CHECK_EVERYTHING();

    CHECK_CAPABILITY(can_access_local_variables);

    // check error condition: JVMTI_ERROR_INVALID_THREAD
    // check error condition: JVMTI_ERROR_THREAD_NOT_ALIVE
    // check error condition: JVMTI_ERROR_ILLEGAL_ARGUMENT
    jvmtiError err = GetLocal_checkArgs(env, &thread, depth, slot, p_value);
    if (err != JVMTI_ERROR_NONE)
        return err;

    // check error condition: JVMTI_ERROR_INVALID_OBJECT
    if (VM_DATA_TYPE_CLASS == var_type && ! is_valid_object(env, *(jobject*) p_value))
        return JVMTI_ERROR_INVALID_OBJECT;

    bool thread_suspended = false;
    // Suspend thread before getting stacks
    vm_thread_t vm_thread;
    if (NULL != thread)
    {
        // Check that this thread is not current
        vm_thread = jthread_get_vm_thread_ptr_safe(thread);
        if (vm_thread != p_TLS_vmthread)
        {
            IDATA UNREF status = hythread_suspend_other((hythread_t)vm_thread);
            assert(TM_ERROR_NONE == status);
            thread_suspended = true;
        }
    }
    else
        vm_thread = p_TLS_vmthread;

    if (interpreter_enabled())
    {
        // TODO: check error condition: JVMTI_ERROR_INVALID_SLOT
        // TODO: check error condition: JVMTI_ERROR_TYPE_MISMATCH
        // TODO: check error condition: JVMTI_ERROR_OPAQUE_FRAME
        // TODO: check error condition: JVMTI_ERROR_NO_MORE_FRAMES

        switch (var_type) {
            case VM_DATA_TYPE_CLASS:
                err = interpreter.interpreter_ti_setObject(env, vm_thread,
                        depth, slot, *(jobject*) p_value);
                break;
            case VM_DATA_TYPE_INT32:
            case VM_DATA_TYPE_F4:
                err = interpreter.interpreter_ti_setLocal32(env, vm_thread,
                        depth, slot, *(int*) p_value);
                break;
            case VM_DATA_TYPE_INT64:
            case VM_DATA_TYPE_F8:
                err = interpreter.interpreter_ti_setLocal64(env, vm_thread,
                        depth, slot, *(int64*) p_value);
                break;
            default:
                DIE(("Error: unrecognized local variable type"));
        }
    }
    else
    {
        GET_JIT_FRAME_CONTEXT;

        tmn_suspend_disable();
        OpenExeJpdaError result;

        switch (var_type) {
            case VM_DATA_TYPE_CLASS:
                if (NULL != *(jobject*) p_value)
                    result = jit->set_local_var(method, jfc, slot,
                        VM_DATA_TYPE_CLASS, &(*(ObjectHandle*) p_value)->object);
                else
                {
                    ManagedObject *n = (ManagedObject *)VM_Global_State::loader_env->managed_null;
                    result = jit->set_local_var(method, jfc, slot,
                        VM_DATA_TYPE_CLASS, &n);
                }

                break;
            case VM_DATA_TYPE_INT32:
            case VM_DATA_TYPE_F4:
            case VM_DATA_TYPE_INT64:
            case VM_DATA_TYPE_F8:
                result = jit->set_local_var(method, jfc, slot, var_type,
                        p_value);
                break;
            default:
                DIE(("Error: unrecognized local variable type"));
        }

        si_free(si);
        tmn_suspend_enable();

        err = jvmti_translate_jit_error(result);
    }

    if (thread_suspended)
        hythread_resume((hythread_t)vm_thread);

    return err;
}
示例#4
0
int test_hythread_thread_suspend(void){
    void **args; 
    hythread_t thread = NULL;
    hythread_thin_monitor_t lock;
    hythread_thin_monitor_t monitor;
    IDATA status;
    int i;

    // create monitors
    status = hythread_thin_monitor_create(&lock);
    tf_assert_same(status, TM_ERROR_NONE);
    status = hythread_thin_monitor_create(&monitor);
    tf_assert_same(status, TM_ERROR_NONE);

    // alloc and set thread start procedure args
    args = (void**)calloc(3, sizeof(void*));
    args[0] = &lock;
    args[1] = &monitor;
    args[2] = 0;

    // create thread
    hythread_suspend_disable();
    status = hythread_thin_monitor_enter(&lock);
    tf_assert_same(status, TM_ERROR_NONE);
    hythread_suspend_enable();

    status = hythread_create(&thread, 0, 0, 0,
        (hythread_entrypoint_t)start_proc, args);
    tf_assert_same(status, TM_ERROR_NONE);

    // waiting start of tested thread
    hythread_suspend_disable();
    status = hythread_thin_monitor_wait(&lock);
    tf_assert_same(status, TM_ERROR_NONE);

    status = hythread_thin_monitor_exit(&lock);
    tf_assert_same(status, TM_ERROR_NONE);
    hythread_suspend_enable();

    // suspend tested thread
    status = hythread_suspend_other(thread);
    tf_assert_same(status, TM_ERROR_NONE);

    // notify tested thread
    hythread_suspend_disable();
    status = hythread_thin_monitor_enter(&monitor);
    tf_assert_same(status, TM_ERROR_NONE);
    status = hythread_thin_monitor_notify_all(&monitor);
    tf_assert_same(status, TM_ERROR_NONE);
    status = hythread_thin_monitor_exit(&monitor);
    tf_assert_same(status, TM_ERROR_NONE);
    hythread_suspend_enable();

    // check tested argument
    for(i = 0; i < 1000; i++) {
        tf_assert_same(args[2], 0);
        hythread_sleep(1);
    }

    // resume thread
    hythread_resume(thread);

    test_thread_join(thread, 1);
    
    tf_assert_same((IDATA)args[2], 1);

    return 0;
}