diff --git a/userspace/units/posix/thread/posix-thread.c b/userspace/units/posix/thread/posix-thread.c index d9231fc2a..1961f5546 100644 --- a/userspace/units/posix/thread/posix-thread.c +++ b/userspace/units/posix/thread/posix-thread.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -30,123 +30,149 @@ #define UNIT_TEST_THREAD_PRIORITY 5 struct test_thread_args { - bool use_priority; - bool check_stop; - bool stop_graceful; - bool use_name; - bool stop_repeat; - bool ret_err; - bool skip_callback; + bool use_priority; + bool check_stop; + bool stop_graceful; + bool use_name; + bool stop_repeat; + bool ret_err; + bool skip_callback; + bool try_join; }; struct unit_test_thread_data { - int thread_created; - int check_priority; - int thread_priority; - int check_stop; - int callback_invoked; - int use_return; + int thread_created; + int check_priority; + int thread_priority; + int check_stop; + int callback_invoked; + int use_return; + int try_join; }; static struct test_thread_args create_normal = { - .use_priority = false, - .check_stop = false, - .stop_graceful = false, - .use_name = true, - .stop_repeat = false, - .ret_err = false, - .skip_callback = false + .use_priority = false, + .check_stop = false, + .stop_graceful = false, + .use_name = true, + .stop_repeat = false, + .ret_err = false, + .skip_callback = false, + .try_join = false }; static struct test_thread_args create_normal_noname = { - .use_priority = false, - .check_stop = false, - .stop_graceful = false, - .use_name = false, - .stop_repeat = false, - .ret_err = false, - .skip_callback = false + .use_priority = false, + .check_stop = false, + .stop_graceful = false, + .use_name = false, + .stop_repeat = false, + .ret_err = false, + .skip_callback = false, + .try_join = false }; static struct test_thread_args create_normal_errret = { - .use_priority = false, - .check_stop = false, - .stop_graceful = false, - .use_name = true, - .stop_repeat = false, - .ret_err = true, - .skip_callback = false + .use_priority = false, + .check_stop = false, + .stop_graceful = false, + .use_name = true, + .stop_repeat = false, + .ret_err = true, + .skip_callback = false, + .try_join = false }; static struct test_thread_args create_priority = { - .use_priority = true, - .check_stop = false, - .stop_graceful = false, - .use_name = true, - .stop_repeat = false, - .ret_err = false, - .skip_callback = false + .use_priority = true, + .check_stop = false, + .stop_graceful = false, + .use_name = true, + .stop_repeat = false, + .ret_err = false, + .skip_callback = false, + .try_join = false }; static struct test_thread_args create_priority_noname = { - .use_priority = true, - .check_stop = false, - .stop_graceful = false, - .use_name = false, - .stop_repeat = false, - .ret_err = false, - .skip_callback = false + .use_priority = true, + .check_stop = false, + .stop_graceful = false, + .use_name = false, + .stop_repeat = false, + .ret_err = false, + .skip_callback = false, + .try_join = false }; static struct test_thread_args check_stop = { - .use_priority = false, - .check_stop = true, - .stop_graceful = false, - .use_name = true, - .stop_repeat = false, - .ret_err = false, - .skip_callback = false + .use_priority = false, + .check_stop = true, + .stop_graceful = false, + .use_name = true, + .stop_repeat = false, + .ret_err = false, + .skip_callback = false, + .try_join = false }; + static struct test_thread_args check_stop_repeat = { - .use_priority = false, - .check_stop = true, - .stop_graceful = false, - .use_name = true, - .stop_repeat = true, - .ret_err = false, - .skip_callback = false + .use_priority = false, + .check_stop = true, + .stop_graceful = false, + .use_name = true, + .stop_repeat = true, + .ret_err = false, + .skip_callback = false, + .try_join = false }; static struct test_thread_args stop_graceful = { - .use_priority = false, - .check_stop = true, - .stop_graceful = true, - .use_name = true, - .stop_repeat = false, - .ret_err = false, - .skip_callback = false + .use_priority = false, + .check_stop = true, + .stop_graceful = true, + .use_name = true, + .stop_repeat = false, + .ret_err = false, + .skip_callback = false, + .try_join = false }; static struct test_thread_args stop_graceful_repeat = { - .use_priority = false, - .check_stop = true, - .stop_graceful = true, - .use_name = true, - .stop_repeat = true, - .ret_err = false, - .skip_callback = false + .use_priority = false, + .check_stop = true, + .stop_graceful = true, + .use_name = true, + .stop_repeat = true, + .ret_err = false, + .skip_callback = false, + .try_join = false }; static struct test_thread_args stop_graceful_skip_callback = { - .use_priority = false, - .check_stop = true, - .stop_graceful = true, - .use_name = true, - .stop_repeat = false, - .ret_err = false, - .skip_callback = true + .use_priority = false, + .check_stop = true, + .stop_graceful = true, + .use_name = true, + .stop_repeat = false, + .ret_err = false, + .skip_callback = true, + .try_join = false }; +#if !defined(__QNX__) +static struct test_thread_args create_try_join = { + .use_priority = false, + .check_stop = false, + .stop_graceful = false, + .use_name = true, + .stop_repeat = false, + .ret_err = false, + .skip_callback = false, + .try_join = true +}; +#endif + static struct nvgpu_thread test_thread; static struct unit_test_thread_data test_data; @@ -165,6 +191,12 @@ static int test_thread_fn(void *args) data->thread_priority = param.sched_priority; } + if (data->try_join) { + if (!EXPECT_BUG(nvgpu_thread_join(&test_thread))) { + data->try_join = 0; + } + } + data->thread_created = 1; if (data->check_stop) { @@ -201,6 +233,10 @@ int test_thread_cycle(struct unit_module *m, struct gk20a *g, void *args) test_data.check_stop = 1; } + if (test_args->try_join == true) { + test_data.try_join = 1; + } + if (test_args->use_priority == false) { if (test_args->use_name == true) { if (test_args->ret_err == true) { @@ -290,6 +326,13 @@ int test_thread_cycle(struct unit_module *m, struct gk20a *g, void *args) } } + if (test_args->try_join == true) { + if (test_data.try_join == 0) { + unit_return_fail(m, + "Attempt to join the same thread didn't invoke bug\n"); + } + } + return UNIT_SUCCESS; } @@ -304,6 +347,9 @@ struct unit_module_test posix_thread_tests[] = { UNIT_TEST(stop_graceful, test_thread_cycle, &stop_graceful, 0), UNIT_TEST(stop_graceful_repeat, test_thread_cycle, &stop_graceful_repeat, 0), UNIT_TEST(stop_graceful_skipcb, test_thread_cycle, &stop_graceful_skip_callback, 0), +#if !defined(__QNX__) + UNIT_TEST(create_try_join, test_thread_cycle, &create_try_join, 0), +#endif }; UNIT_MODULE(posix_thread, posix_thread_tests, UNIT_PRIO_POSIX_TEST); diff --git a/userspace/units/posix/thread/posix-thread.h b/userspace/units/posix/thread/posix-thread.h index a0849d71c..83517a96e 100644 --- a/userspace/units/posix/thread/posix-thread.h +++ b/userspace/units/posix/thread/posix-thread.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -63,6 +63,12 @@ * 4) Wait for the thread to be created by polling for a shared variable. * 5) Return Success once the thread function is called and the shared * variable is set which indicates a successful thread creation. + * 6) Above steps are done for thread with a name, thread without a name + * and thread function which returns an error value. + * 7) For code coverage, based on a passed argument the created thread tries + * to join with itself expecting a BUG callback. This should trigger a BUG + * as expected by the calling thread. This test is run only if QNX is not + * defined, as there is a difference in the return values. * * Thread creation with a priority value * 1) Reset all global and shared variables to 0. @@ -74,6 +80,7 @@ * 6) In some host machines, permission is not granted to create threads * with priority. In that case skip the test by returning PASS. * 7) Return PASS if the thread is created with requested priority. + * 8) Above steps are done for thread with a name and without a name. * * Thread stop * 1) Follow steps 1 - 4 of Thread creation scenario.