Beispiel #1
0
/**
 * Returns the number of times given thread have entered given monitor;
 *
 * If the given monitor is not owned by this thread, 0 is returned.
 *
 * @param[in] monitor monitor those owner needs to be determined
 * @param[in] owner thread which owns the monitor
 */
IDATA VMCALL jthread_get_lock_recursion(jobject monitor, jthread owner)
{
    assert(monitor);

    hythread_t given_thread = owner ? jthread_get_native_thread(owner) : NULL;

    hythread_suspend_disable();
    hythread_thin_monitor_t *lockword = vm_object_get_lockword_addr(monitor);
    hythread_t lock_owner = hythread_thin_monitor_get_owner(lockword);

    IDATA recursion = 0;
    if (lock_owner
        && (!given_thread
            || hythread_get_id(lock_owner) == hythread_get_id(given_thread)))
    {
        recursion = hythread_thin_monitor_get_recursion(lockword);
    }
    hythread_suspend_enable();

    return recursion;
} // jthread_get_lock_recursion
Beispiel #2
0
ncaiError JNICALL
ncaiGetThreadInfo(ncaiEnv *env, ncaiThread thread, ncaiThreadInfo *info_ptr)
{
    TRACE2("ncai.thread", "ncaiGetThreadsInfo called");
    SuspendEnabledChecker sec;

    if (env == NULL)
        return NCAI_ERROR_INVALID_ENVIRONMENT;

    if (info_ptr == NULL)
        return NCAI_ERROR_NULL_POINTER;

    if (thread == NULL)
        return NCAI_ERROR_INVALID_THREAD;

    hythread_t hythread = reinterpret_cast<hythread_t>(thread);

    if (!ncai_thread_is_alive(hythread))
        return NCAI_ERROR_THREAD_NOT_ALIVE;

    jthread java_thread = jthread_get_java_thread(hythread);

    if (java_thread != NULL)
    {
        JNIEnv* jni_env = jthread_get_vm_thread(hythread)->jni_env;
        jclass cl = GetObjectClass(jni_env, java_thread);
        jmethodID id = jni_env->GetMethodID(cl, "getName","()Ljava/lang/String;");
        jstring  name = jni_env->CallObjectMethod(java_thread, id);
        info_ptr->name = (char *)jni_env->GetStringUTFChars(name, NULL);

        info_ptr->kind = NCAI_THREAD_JAVA;
        return NCAI_ERROR_NONE;
    }

    info_ptr->kind = NCAI_THREAD_VM_INTERNAL;

    const char* name_int = "native_0x";
    size_t name_len = strlen(name_int) + 4 + 1;
    info_ptr->name = (char*)ncai_alloc(name_len);
    assert(info_ptr->name);
    sprintf(info_ptr->name, "%s%04X", name_int, hythread_get_id(hythread));

    return NCAI_ERROR_NONE;
}
/**
 * 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;
}