/** * Returns true if specified thread holds the lock associated with the given monitor. * * @param[in] thread thread which may hold the lock * @param[in] monitor object those monitor is possibly locked * @return true if thread holds the lock, false otherwise; */ jboolean VMCALL jthread_holds_lock(jthread thread, jobject monitor) { jthread lock_owner; IDATA status = jthread_get_lock_owner(monitor, &lock_owner); assert(status == TM_ERROR_NONE); hythread_suspend_disable(); jboolean result = vm_objects_are_equal(thread, lock_owner); hythread_suspend_enable(); return result; } // jthread_holds_lock
int test_jthread_get_lock_owner(void) { tested_thread_sturct_t *tts; tested_thread_sturct_t *critical_tts = NULL; jthread lock_owner = NULL; int blocked_count; int i; hysem_create(&mon_enter, 0 , 1); // Initialize tts structures and run all tested threads tested_threads_run(run_for_test_jthread_get_lock_owner); for (i = 0; i < MAX_TESTED_THREAD_NUMBER; i++){ blocked_count = 0; critical_tts = NULL; hysem_wait(mon_enter); reset_tested_thread_iterator(&tts); while(next_tested_thread(&tts)){ while(tts->phase == TT_PHASE_NONE) { // thread is not started yet hythread_yield(); } if (tts->phase == TT_PHASE_IN_CRITICAL_SECTON){ tf_assert_null(critical_tts); critical_tts = tts; } else if (tts->phase == TT_PHASE_WAITING_ON_MONITOR){ blocked_count++; } } tf_assert(critical_tts); // thread in critical section found tf_assert_same(blocked_count, MAX_TESTED_THREAD_NUMBER - i - 1); tf_assert_same(jthread_get_lock_owner(critical_tts->monitor, &lock_owner), TM_ERROR_NONE); tf_assert(lock_owner); tf_assert_same(critical_tts->java_thread->object, lock_owner->object); tested_thread_send_stop_request(critical_tts); tested_thread_wait_ended(critical_tts); check_tested_thread_phase(critical_tts, TT_PHASE_DEAD); } // Terminate all threads and clear tts structures tested_threads_destroy(); return TEST_PASSED; }
/** * Checks for the deadlock conditions within the specified thread list. * * @param[in] thread_list thread list where to search for deadlock conditions * @param[in] thread_count number of threads in the thread list * @param[out] dead_list deadlocked threads * @param[out] dead_count number of deadlocked threads */ IDATA VMCALL jthread_get_deadlocked_threads(jthread * thread_list, jint thread_count, jthread ** dead_list, jint * dead_count) { int deads_size; int deads_base; int deads_top; int output_top; IDATA status = TM_ERROR_NONE; jthread *deads = (jthread *) malloc(sizeof(jthread) * thread_count); jthread *output = (jthread *) malloc(sizeof(jthread) * thread_count); if ((deads == NULL) || (output == NULL)) { status = TM_ERROR_OUT_OF_MEMORY; goto free_allocated_memory; } deads_size = 1; deads_base = 0; deads_top = 0; output_top = 0; for (jint i = 0; i < thread_count; i++) { jthread thread = thread_list[i]; output[output_top] = thread; while (true) { jobject monitor; IDATA status = jthread_get_contended_monitor(thread, &monitor); if (status != TM_ERROR_NONE) { goto free_allocated_memory; } if (!monitor) { deads_top = deads_base; // remove frame break; } if (jthread_find_deads(thread, deads, deads_base, deads_top)) { output_top++; deads_base = deads_top; // add frame break; } if (deads_top == deads_size) { // status = deads_expand(&deads, deads_size); if (status != TM_ERROR_NONE) return status; } deads[deads_top] = thread; deads_top++; status = jthread_get_lock_owner(monitor, &thread); if (status != TM_ERROR_NONE) { goto free_allocated_memory; } } } if (output_top > 0) { output = (jthread*)realloc(output, sizeof(jthread) * output_top); if (!output) { status = TM_ERROR_OUT_OF_MEMORY; goto free_allocated_memory; } *dead_list = output; } else { *dead_list = NULL; } *dead_count = output_top; if (!deads) { free(deads); } return TM_ERROR_NONE; free_allocated_memory: if (!deads) { free(deads); } if (!output) { free(output); } return status; } // jthread_get_deadlocked_threads