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