blob: d92ed29cc99b2f14d64d5e3da38091fb712b2d82 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "testframe.h"
#include "thread_unit_test_utils.h"
#include <jthread.h>
#include <ti_thread.h>
static hysem_t mon_enter;
/**
* Test jthread_get_all_threads()
* Test jthread_get_thread_count()
*/
int test_jthread_get_all_threads(void)
{
tested_thread_sturct_t *tts;
jint all_threads_count;
jint thread_count;
jint initial_thread_count;
jint initial_all_threads_count;
jthread *threads = NULL;
int i;
JNIEnv * jni_env = jthread_get_JNI_env(jthread_self());
tf_assert_same(jthread_get_thread_count(&initial_thread_count), TM_ERROR_NONE);
tf_assert_same(jthread_get_all_threads(&threads, &initial_all_threads_count), TM_ERROR_NONE);
// Initialize tts structures
tested_threads_init(TTS_INIT_COMMON_MONITOR);
tf_assert_same(jthread_get_thread_count(&thread_count), TM_ERROR_NONE);
tf_assert_same(jthread_get_all_threads(&threads, &all_threads_count), TM_ERROR_NONE);
tf_assert_same(thread_count, initial_thread_count);
tf_assert_same(all_threads_count, initial_all_threads_count);
tf_assert_not_null(threads);
i = 0;
reset_tested_thread_iterator(&tts);
while(next_tested_thread(&tts)){
tts->attrs.proc = default_run_for_test;
tts->attrs.arg = tts;
tf_assert_same(jthread_create_with_function(jni_env, tts->java_thread, &tts->attrs), TM_ERROR_NONE);
tested_thread_wait_started(tts);
tts->native_thread = jthread_get_native_thread(tts->java_thread);
check_tested_thread_phase(tts, TT_PHASE_RUNNING);
tf_assert_same(jthread_get_thread_count(&thread_count), TM_ERROR_NONE);
tf_assert_same(jthread_get_all_threads(&threads, &all_threads_count), TM_ERROR_NONE);
i++;
tf_assert_same(thread_count, i + initial_thread_count);
tf_assert_same(all_threads_count, i + initial_all_threads_count);
compare_threads(threads, i, 0);
}
// Terminate all threads (not needed here) and clear tts structures
tested_threads_destroy();
return TEST_PASSED;
} // test_jthread_get_all_threads
/*
* Test jthread_get_blocked_count()
*/
void JNICALL run_for_test_jthread_get_blocked_count(jvmtiEnv * jvmti_env, JNIEnv * jni_env, void *args){
tested_thread_sturct_t * tts = (tested_thread_sturct_t *) args;
jobject monitor = tts->monitor;
IDATA status;
tts->phase = TT_PHASE_WAITING_ON_MONITOR;
tested_thread_started(tts);
status = jthread_monitor_enter(monitor);
// Begin critical section
tts->phase = (status == TM_ERROR_NONE ? TT_PHASE_IN_CRITICAL_SECTON : TT_PHASE_ERROR);
hysem_set(mon_enter, 1);
tested_thread_wait_for_stop_request(tts);
status = jthread_monitor_exit(monitor);
// End critical section
tts->phase = (status == TM_ERROR_NONE ? TT_PHASE_DEAD : TT_PHASE_ERROR);
tested_thread_ended(tts);
} // run_for_test_jthread_get_blocked_count
int test_jthread_get_blocked_count(void)
{
tested_thread_sturct_t *tts;
tested_thread_sturct_t *critical_tts;
int i;
int waiting_on_monitor_nmb;
tf_assert_same(hysem_create(&mon_enter, 0, 1), TM_ERROR_NONE);
// Initialize tts structures and run all tested threads
tested_threads_run(run_for_test_jthread_get_blocked_count);
for (i = 0; i < MAX_TESTED_THREAD_NUMBER; i++){
int cycles = MAX_TIME_TO_WAIT / CLICK_TIME_MSEC;
tf_assert_same(hysem_wait(mon_enter), TM_ERROR_NONE);
critical_tts = NULL;
reset_tested_thread_iterator(&tts);
while(next_tested_thread(&tts)){
if (tts->phase == TT_PHASE_IN_CRITICAL_SECTON){
tf_assert(critical_tts == NULL);
critical_tts = tts;
}
}
waiting_on_monitor_nmb = 0;
while ((MAX_TESTED_THREAD_NUMBER - i > waiting_on_monitor_nmb + 1) && (cycles-- > 0)) {
tf_assert_same(jthread_get_blocked_count(&waiting_on_monitor_nmb), TM_ERROR_NONE);
sleep_a_click();
}
if (cycles < 0){
tf_fail("Wrong number waiting on monitor threads");
}
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;
} // test_jthread_get_blocked_count
/*
* Test jthread_get_deadlocked_threads()
*/
void JNICALL run_for_test_jthread_get_deadlocked_threads(jvmtiEnv * jvmti_env, JNIEnv * jni_env, void *args)
{
tested_thread_sturct_t * tts = (tested_thread_sturct_t *) args;
IDATA status = TM_ERROR_NONE;
tts->phase = TT_PHASE_WAITING_ON_MONITOR;
status = jthread_monitor_enter(tts->monitor);
tts->phase = TT_PHASE_RUNNING;
tested_thread_started(tts);
tested_thread_wait_for_stop_request(tts);
tts->phase = TT_PHASE_WAITING_ON_MONITOR;
status = jthread_monitor_enter(
get_tts(MAX_TESTED_THREAD_NUMBER - (tts->my_index + 1))->monitor);
tts->phase = status == TM_ERROR_NONE ? TT_PHASE_DEAD : TT_PHASE_ERROR;
tested_thread_ended(tts);
} // run_for_test_jthread_get_deadlocked_threads
int test_jthread_get_deadlocked_threads(void)
{
tested_thread_sturct_t * tts;
jthread *thread_list;
int dead_list_count;
jthread *dead_list;
int count;
// Initialize tts structures and run all tested threads
tested_threads_run_with_different_monitors(run_for_test_jthread_get_deadlocked_threads);
thread_list =
(jthread*)calloc(MAX_TESTED_THREAD_NUMBER, sizeof(jthread*));
tf_assert(thread_list && "failed to alloc memory");
reset_tested_thread_iterator(&tts);
while(next_tested_thread(&tts)) {
thread_list[tts->my_index] = tts->java_thread;
}
tf_assert_same(jthread_get_deadlocked_threads(thread_list, MAX_TESTED_THREAD_NUMBER,
&dead_list, &dead_list_count), TM_ERROR_NONE);
tf_assert_same(dead_list_count, 0);
reset_tested_thread_iterator(&tts);
while(next_tested_thread(&tts)) {
tested_thread_send_stop_request(tts);
}
reset_tested_thread_iterator(&tts);
while(next_tested_thread(&tts)) {
count = 0;
if ((MAX_TESTED_THREAD_NUMBER % 2)
&& (tts->my_index == MAX_TESTED_THREAD_NUMBER / 2))
{
while (hythread_is_alive(tts->native_thread)) {
// wait until the state is changed
hythread_sleep(SLEEP_TIME);
if (tts->phase == TT_PHASE_ERROR || ++count > (MAX_TIME_TO_WAIT/SLEEP_TIME)) {
tf_fail("thread failed to change state on WAITING");
}
}
log_info("Thread %d is dead", tts->my_index);
check_tested_thread_phase(tts, TT_PHASE_DEAD);
thread_list[tts->my_index] = jthread_self();
} else {
while (!hythread_is_blocked_on_monitor_enter(tts->native_thread)) {
// wait until the state is changed
hythread_sleep(SLEEP_TIME);
if (tts->phase == TT_PHASE_ERROR || ++count > (MAX_TIME_TO_WAIT/SLEEP_TIME)) {
tf_fail("thread failed to change state on WAITING");
}
}
log_info("Thread %d is blocked on monitor", tts->my_index);
check_tested_thread_phase(tts, TT_PHASE_WAITING_ON_MONITOR);
}
}
tf_assert_same(jthread_get_deadlocked_threads(thread_list, MAX_TESTED_THREAD_NUMBER,
&dead_list, &dead_list_count), TM_ERROR_NONE);
log_info("Deadlocked thread numbre is %d", dead_list_count);
tf_assert_same(dead_list_count,
((MAX_TESTED_THREAD_NUMBER % 2)
? MAX_TESTED_THREAD_NUMBER - 1 : MAX_TESTED_THREAD_NUMBER));
count = 0;
reset_tested_thread_iterator(&tts);
while(next_tested_thread(&tts)) {
if ((MAX_TESTED_THREAD_NUMBER % 2)
&& (tts->my_index == MAX_TESTED_THREAD_NUMBER / 2))
{
continue;
} else {
tf_assert_same(dead_list[count++], tts->java_thread);
log_info("Thread %d is deadlocked", tts->my_index);
hythread_set_state(tts->native_thread, TM_THREAD_STATE_TERMINATED);
hythread_cancel(tts->native_thread);
}
}
// Terminate all threads and clear tts structures
tested_threads_destroy();
return TEST_PASSED;
} // test_jthread_get_deadlocked_threads
/**
* Test jthread_get_waited_count()
*/
void JNICALL run_for_test_jthread_get_waited_count(jvmtiEnv * jvmti_env, JNIEnv * jni_env, void *args)
{
tested_thread_sturct_t * tts = (tested_thread_sturct_t *) args;
jobject monitor = tts->monitor;
IDATA status;
tts->phase = TT_PHASE_RUNNING;
tested_thread_started(tts);
// Enter critical section
status = jthread_monitor_enter(monitor);
tts->phase = (status == TM_ERROR_NONE ? TT_PHASE_WAITING_ON_WAIT : TT_PHASE_ERROR);
// Wait on monitor
status = jthread_monitor_wait(monitor);
if (status != TM_ERROR_NONE){
tts->phase = TT_PHASE_ERROR;
jthread_monitor_exit(monitor);
tested_thread_ended(tts);
return;
}
// Exit critical section
status = jthread_monitor_exit(monitor);
tts->phase = (status == TM_ERROR_NONE ? TT_PHASE_DEAD : TT_PHASE_ERROR);
tested_thread_ended(tts);
} // run_for_test_jthread_get_waited_count
int test_jthread_get_waited_count(void)
{
int count;
int waiting_nmb;
jobject monitor;
tested_thread_sturct_t * tts;
// Initialize tts structures and run all tested threads
tested_threads_run(run_for_test_jthread_get_waited_count);
reset_tested_thread_iterator(&tts);
while(next_tested_thread(&tts)){
count = 0;
while (!hythread_is_waiting(tts->native_thread)) {
// wait until the state is changed
hythread_sleep(SLEEP_TIME);
if (tts->phase == TT_PHASE_ERROR || ++count > (MAX_TIME_TO_WAIT/SLEEP_TIME)) {
tf_fail("thread failed to change state on WAITING");
}
}
check_tested_thread_phase(tts, TT_PHASE_WAITING_ON_WAIT);
log_info("Thread %d is waiting.", tts->my_index);
}
tf_assert_same(jthread_get_waited_count(&waiting_nmb), TM_ERROR_NONE);
log_info("Waiting threads count is %d", waiting_nmb);
tf_assert_same(waiting_nmb, MAX_TESTED_THREAD_NUMBER);
log_info("Release all threads");
monitor = get_tts(0)->monitor;
tf_assert_same(jthread_monitor_enter(monitor), TM_ERROR_NONE);
tf_assert_same(jthread_monitor_notify_all(monitor), TM_ERROR_NONE);
tf_assert_same(jthread_monitor_exit(monitor), TM_ERROR_NONE);
// Terminate all threads and clear tts structures
tested_threads_destroy();
return TEST_PASSED;
} // test_jthread_get_waited_count
TEST_LIST_START
TEST(test_jthread_get_all_threads)
TEST(test_jthread_get_blocked_count)
TEST(test_jthread_get_deadlocked_threads)
TEST(test_jthread_get_waited_count)
TEST_LIST_END;