blob: ba269e8c95de7697bb3cbf792229b30bc1c0e082 [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 "thread_manager.h"
typedef struct proc_param {
hythread_group_t group;
UDATA stacksize;
jint priority;
hylatch_t start;
hylatch_t end;
} proc_param;
static int start_proc(void *args) {
proc_param *attrs = (proc_param *)args;
tf_assert_same(hythread_get_priority(hythread_self()), attrs->priority);
tf_assert_same(hythread_self()->group, attrs->group);
hylatch_count_down(attrs->end);
return 0;
} // start_proc
static int start_proc_empty(void *args) {
proc_param *attrs = (proc_param *)args;
hylatch_count_down(attrs->start);
hylatch_wait(attrs->end);
return 0;
} // start_proc_empty
int test_hythread_self_base(void) {
hythread_t thread;
// check that this thread is attached to VM
tf_assert(thread = hythread_self());
return 0;
} // test_hythread_self_base
/*
* Test tm_create(..)
*/
int test_hythread_create(void) {
proc_param *args;
hythread_t thread;
IDATA status;
args = (proc_param*)calloc(1, sizeof(proc_param));
tf_assert(args && "alloc proc_params failed");
status = hythread_group_create(&args->group);
tf_assert(status == TM_ERROR_NONE && "thread group creation failed");
status = hylatch_create(&args->end, 1);
tf_assert(status == TM_ERROR_NONE && "latch creation failed");
args->priority = 1;
thread = (hythread_t)calloc(1, hythread_get_struct_size());
assert(thread);
status = hythread_create_ex(thread, args->group, 1024000, 1, NULL,
(hythread_entrypoint_t)start_proc, (void*)args);
tf_assert(status == TM_ERROR_NONE && "thread creation failed");
// Wait util tested thread have finished.
status = hylatch_wait(args->end);
tf_assert(status == TM_ERROR_NONE && "thread finished failed");
status = hylatch_destroy(args->end);
tf_assert(status == TM_ERROR_NONE && "latch destroy failed");
hythread_sleep(SLEEP_TIME);
hythread_group_release(args->group);
free(args);
return TEST_PASSED;
}
/**
* Waits until count of running threads in specified group
* reaches 'count' or less
*/
static void wait_for_all_treads_are_terminated(hythread_group_t group, int count)
{
int max_tries = 1000; // Maximum count of iterations
while (max_tries--)
{
int n = 0;
hythread_t thread;
hythread_iterator_t iterator = hythread_iterator_create(group);
while(hythread_iterator_has_next(iterator)) {
thread = hythread_iterator_next(&iterator);
if (!hythread_is_terminated(thread))
++n;
}
hythread_iterator_release(&iterator);
if (n <= count)
break;
hythread_yield();
}
// 0.1s to let system threads finish their work
hythread_sleep(100);
} // wait_for_all_treads_are_terminated
int test_hythread_iterator(void) {
int i;
const int n = 100;
IDATA status;
proc_param *args;
hythread_t thread = NULL;
hythread_iterator_t iterator;
args = (proc_param*)calloc(1, sizeof(proc_param));
tf_assert(args && "alloc proc_params failed");
status = hythread_group_create(&args->group);
tf_assert(status == TM_ERROR_NONE && "create group failed");
status = hylatch_create(&args->start, n);
tf_assert(status == TM_ERROR_NONE && "latch creation failed");
status = hylatch_create(&args->end, 1);
tf_assert(status == TM_ERROR_NONE && "latch creation failed");
for (i = 0; i < n; i++) {
thread = (hythread_t)calloc(1, hythread_get_struct_size());
assert(thread);
status = hythread_create_ex(thread, args->group, 0, 0, NULL,
(hythread_entrypoint_t)start_proc_empty, (void*)args);
tf_assert(status == TM_ERROR_NONE && "test thread creation failed");
}
// Wait util all threads have started.
status = hylatch_wait(args->start);
tf_assert(status == TM_ERROR_NONE && "start waiting failed");
iterator = hythread_iterator_create(args->group);
tf_assert(iterator && "interator creation failed");
printf ("iterator size: %d\n", (int)hythread_iterator_size(iterator));
tf_assert(hythread_iterator_size(iterator) == n && "iterator size");
i = 0;
while(hythread_iterator_has_next(iterator)) {
i++;
thread = hythread_iterator_next(&iterator);
tf_assert(hythread_is_alive(thread) && "thread is not alive!");
}
tf_assert(i == n && "wrong number of tested threads");
status = hythread_iterator_release(&iterator);
tf_assert(status == TM_ERROR_NONE && "release iterator failed");
// Notify all threads
status = hylatch_count_down(args->end);
tf_assert(status == TM_ERROR_NONE && "all threads notify failed");
wait_for_all_treads_are_terminated(args->group, i - n);
status = hylatch_destroy(args->start);
tf_assert(status == TM_ERROR_NONE && "start latch destroy failed");
status = hylatch_destroy(args->end);
tf_assert(status == TM_ERROR_NONE && "end latch destroy failed");
hythread_sleep(SLEEP_TIME);
hythread_group_release(args->group);
free(args);
return TEST_PASSED;
} // test_hythread_iterator
int test_hythread_iterator_default(void) {
int i;
const int n = 100;
IDATA status;
proc_param *args;
hythread_t thread = NULL;
hythread_iterator_t iterator;
args = (proc_param*)calloc(1, sizeof(proc_param));
tf_assert(args && "alloc proc_params failed");
status = hylatch_create(&args->start, n);
tf_assert(status == TM_ERROR_NONE && "latch creation failed");
status = hylatch_create(&args->end, 1);
tf_assert(status == TM_ERROR_NONE && "latch creation failed");
for (i = 0; i < n; i++) {
status = hythread_create(NULL, 0, 0, 0,
(hythread_entrypoint_t)start_proc_empty, (void*)args);
tf_assert(status == TM_ERROR_NONE && "test thread creation failed");
}
// Wait util all threads have started.
status = hylatch_wait(args->start);
tf_assert(status == TM_ERROR_NONE && "start waiting failed");
iterator = hythread_iterator_create(args->group);
tf_assert(iterator && "interator creation failed");
printf ("default group iterator size: %d\n", (int)hythread_iterator_size(iterator));
tf_assert(hythread_iterator_size(iterator) >= n && "iterator size");
i = 0;
while(hythread_iterator_has_next(iterator)) {
thread = hythread_iterator_next(&iterator);
if (hythread_is_alive(thread)) {
i++;
}
}
tf_assert(i >= n && "wrong number of tested threads");
status = hythread_iterator_release(&iterator);
tf_assert(status == TM_ERROR_NONE && "release iterator failed");
// Notify all threads
status = hylatch_count_down(args->end);
tf_assert(status == TM_ERROR_NONE && "all threads notify failed");
wait_for_all_treads_are_terminated(NULL, i - n);
status = hylatch_destroy(args->start);
tf_assert(status == TM_ERROR_NONE && "start latch destroy failed");
status = hylatch_destroy(args->end);
tf_assert(status == TM_ERROR_NONE && "end latch destroy failed");
free(args);
return TEST_PASSED;
} // test_hythread_iterator_default
/*
* Test tm_create(..)
*/
int test_hythread_create_many(void){
int i;
const int n = 10;
IDATA status;
proc_param *args;
hythread_t thread;
args = (proc_param*)calloc(1, sizeof(proc_param));
tf_assert(args && "alloc proc_params failed");
status = hythread_group_create(&args->group);
tf_assert(status == TM_ERROR_NONE && "create group failed");
status = hylatch_create(&args->start, n);
tf_assert(status == TM_ERROR_NONE && "latch creation failed");
status = hylatch_create(&args->end, 1);
tf_assert(status == TM_ERROR_NONE && "latch creation failed");
for (i = 0; i < n; i++) {
thread = (hythread_t)calloc(1, hythread_get_struct_size());
assert(thread);
status = hythread_create_ex(thread, args->group, 0, 0, NULL,
(hythread_entrypoint_t)start_proc_empty, (void*)args);
tf_assert(status == TM_ERROR_NONE && "test thread creation failed");
}
// Wait util all threads have started.
status = hylatch_wait(args->start);
tf_assert(status == TM_ERROR_NONE && "start waiting failed");
// huck to get group_count from hythread_group_t structure
i = hythread_iterator_size((hythread_iterator_t)thread);
tf_assert(i == n && "incorrect threads count");
// Notify all threads
status = hylatch_count_down(args->end);
tf_assert(status == TM_ERROR_NONE && "all threads notify failed");
wait_for_all_treads_are_terminated(args->group, i - n);
status = hylatch_destroy(args->start);
tf_assert(status == TM_ERROR_NONE && "start latch destroy failed");
status = hylatch_destroy(args->end);
tf_assert(status == TM_ERROR_NONE && "end latch destroy failed");
hythread_sleep(SLEEP_TIME);
hythread_group_release(args->group);
free(args);
return TEST_PASSED;
} // test_hythread_create_many
TEST_LIST_START
TEST(test_hythread_self_base)
TEST(test_hythread_create)
TEST(test_hythread_create_many)
TEST(test_hythread_iterator)
TEST(test_hythread_iterator_default)
TEST_LIST_END;