mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
gpu: nvgpu: add more tests for cond unit
Add more tests as part of unit tests for condition variables. Jira NVGPU-4478 Change-Id: I6256727b2174759a71fb1a3fecd18dde5dcdd9cd Signed-off-by: ajesh <akv@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2274149 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Philip Elcan <pelcan@nvidia.com> Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> Reviewed-by: Shashank Singh <shashsingh@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2019-2020, 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"),
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <nvgpu/cond.h>
|
||||
#include <nvgpu/thread.h>
|
||||
#include <nvgpu/timers.h>
|
||||
|
||||
#include "posix-cond.h"
|
||||
|
||||
@@ -338,6 +339,72 @@ int test_cond_init_destroy(struct unit_module *m,
|
||||
return UNIT_SUCCESS;
|
||||
}
|
||||
|
||||
int test_cond_bug(struct unit_module *m,
|
||||
struct gk20a *g, void *args)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(&test_cond, 0, sizeof(struct nvgpu_cond));
|
||||
|
||||
if(!EXPECT_BUG(nvgpu_cond_signal(NULL))) {
|
||||
unit_return_fail(m, "BUG not called for NULL cond var\n");
|
||||
}
|
||||
|
||||
if(!EXPECT_BUG(nvgpu_cond_signal(&test_cond))) {
|
||||
unit_return_fail(m,
|
||||
"BUG not called for uninitialized cond var\n");
|
||||
}
|
||||
|
||||
if(!EXPECT_BUG(nvgpu_cond_signal_interruptible(NULL))) {
|
||||
unit_return_fail(m, "BUG not called for NULL cond var\n");
|
||||
}
|
||||
|
||||
if(!EXPECT_BUG(nvgpu_cond_signal_interruptible(&test_cond))) {
|
||||
unit_return_fail(m,
|
||||
"BUG not called for uninitialized cond var\n");
|
||||
}
|
||||
|
||||
if(!EXPECT_BUG(nvgpu_cond_destroy(NULL))) {
|
||||
unit_return_fail(m, "BUG not called for NULL cond var\n");
|
||||
}
|
||||
|
||||
if(!EXPECT_BUG(nvgpu_cond_signal_locked(NULL))) {
|
||||
unit_return_fail(m, "BUG not called for NULL cond var\n");
|
||||
}
|
||||
|
||||
if(!EXPECT_BUG(nvgpu_cond_signal_locked(&test_cond))) {
|
||||
unit_return_fail(m,
|
||||
"BUG not called for uninitialized cond var\n");
|
||||
}
|
||||
|
||||
ret = nvgpu_cond_broadcast(NULL);
|
||||
if (ret != -EINVAL) {
|
||||
unit_return_fail(m, "NULL cond var not handled\n");
|
||||
}
|
||||
|
||||
ret = nvgpu_cond_broadcast(&test_cond);
|
||||
if (ret != -EINVAL) {
|
||||
unit_return_fail(m, "Uninitialized cond var not handled\n");
|
||||
}
|
||||
|
||||
ret = nvgpu_cond_broadcast_interruptible(NULL);
|
||||
if (ret != -EINVAL) {
|
||||
unit_return_fail(m, "NULL cond var not handled\n");
|
||||
}
|
||||
|
||||
ret = nvgpu_cond_broadcast_interruptible(&test_cond);
|
||||
if (ret != -EINVAL) {
|
||||
unit_return_fail(m, "Uninitialized cond var not handled\n");
|
||||
}
|
||||
|
||||
ret = nvgpu_cond_broadcast_locked(&test_cond);
|
||||
if (ret != -EINVAL) {
|
||||
unit_return_fail(m, "Uninitialized cond var not handled\n");
|
||||
}
|
||||
|
||||
return UNIT_SUCCESS;
|
||||
}
|
||||
|
||||
int test_cond_signal(struct unit_module *m,
|
||||
struct gk20a *g, void *args)
|
||||
{
|
||||
@@ -423,8 +490,51 @@ int test_cond_signal(struct unit_module *m,
|
||||
return UNIT_SUCCESS;
|
||||
}
|
||||
|
||||
int test_cond_timeout(struct unit_module *m,
|
||||
struct gk20a *g, void *args)
|
||||
{
|
||||
int ret;
|
||||
unsigned int timeout;
|
||||
signed long ts_before, ts_after, delay;
|
||||
|
||||
memset(&test_cond, 0, sizeof(struct nvgpu_cond));
|
||||
timeout = 10;
|
||||
|
||||
ret = nvgpu_cond_init(&test_cond);
|
||||
if (ret != 0) {
|
||||
unit_return_fail(m, "Cond init failed\n");
|
||||
}
|
||||
|
||||
ts_before = nvgpu_current_time_us();
|
||||
nvgpu_cond_lock(&test_cond);
|
||||
|
||||
ret = nvgpu_cond_timedwait(&test_cond, &timeout);
|
||||
if (ret != ETIMEDOUT) {
|
||||
nvgpu_cond_unlock(&test_cond);
|
||||
nvgpu_cond_destroy(&test_cond);
|
||||
unit_return_fail(m, "Cond timed wait return error %d\n", ret);
|
||||
}
|
||||
|
||||
ts_after = nvgpu_current_time_us();
|
||||
delay = ts_after - ts_before;
|
||||
delay /= 1000;
|
||||
|
||||
if (delay < 10) {
|
||||
nvgpu_cond_unlock(&test_cond);
|
||||
nvgpu_cond_destroy(&test_cond);
|
||||
unit_return_fail(m,
|
||||
"Timed wait Duration incorrect\n");
|
||||
}
|
||||
|
||||
nvgpu_cond_unlock(&test_cond);
|
||||
nvgpu_cond_destroy(&test_cond);
|
||||
|
||||
return UNIT_SUCCESS;
|
||||
}
|
||||
|
||||
struct unit_module_test posix_cond_tests[] = {
|
||||
UNIT_TEST(init, test_cond_init_destroy, NULL, 0),
|
||||
UNIT_TEST(bug_cond, test_cond_bug, NULL, 0),
|
||||
UNIT_TEST(wait_signal, test_cond_signal, &signal_normal, 0),
|
||||
UNIT_TEST(wait_signal_int, test_cond_signal, &signal_int, 0),
|
||||
UNIT_TEST(wait_signal_locked, test_cond_signal, &signal_locked, 0),
|
||||
@@ -435,6 +545,7 @@ struct unit_module_test posix_cond_tests[] = {
|
||||
UNIT_TEST(wait_condition, test_cond_signal, &condition_wait, 0),
|
||||
UNIT_TEST(wait_condition_int, test_cond_signal, &condition_wait_int, 0),
|
||||
UNIT_TEST(wait_condition_locked, test_cond_signal, &condition_wait_locked, 0),
|
||||
UNIT_TEST(wait_timeout, test_cond_timeout, NULL, 0),
|
||||
};
|
||||
|
||||
UNIT_MODULE(posix_cond, posix_cond_tests, UNIT_PRIO_POSIX_TEST);
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
* struct nvgpu_cond
|
||||
*
|
||||
* Output:
|
||||
* The test returns PASS if cond variable initiaisation and cleanup functions
|
||||
* The test returns PASS if cond variable initialization and cleanup functions
|
||||
* returns expected success values and internal variables in cond variable
|
||||
* structure is initialised with proper values.
|
||||
* The test returns FAIL if either initialisation or cleanup routine fails.
|
||||
@@ -64,6 +64,37 @@
|
||||
int test_cond_init_destroy(struct unit_module *m,
|
||||
struct gk20a *g, void *args);
|
||||
|
||||
/**
|
||||
* Test specification for test_cond_bug
|
||||
*
|
||||
* Description: Test NULL and uninitialized cond vars.
|
||||
*
|
||||
* Test Type: Feature, Error injection
|
||||
*
|
||||
* Inputs:
|
||||
* 1) Global instance of struct nvgpu_cond.
|
||||
*
|
||||
* Steps:
|
||||
* 1) Call the condition variable functions with NULL as input parameter.
|
||||
* 2) Make sure that all the called functions either invoke BUG or return
|
||||
* an error value for NULL value as input parameter.
|
||||
* 3) Call the condition variable function with uninitialized condition
|
||||
* variable as input parameter.
|
||||
* 4) Make sure that all the called functions either invokes BUG or returns
|
||||
* an error value for uninitialized condition variable passed as input
|
||||
* parameter.
|
||||
*
|
||||
* Output:
|
||||
* The test returns PASS if all the NULL and uninitialized input parameters
|
||||
* are handled by the condition variable functions by either calling BUG or by
|
||||
* returning an error value.
|
||||
* The test returns FAIL if any of the NULL or uninitialized condition variable
|
||||
* passed as input parameter is not handled as expected.
|
||||
*
|
||||
*/
|
||||
int test_cond_bug(struct unit_module *m,
|
||||
struct gk20a *g, void *args);
|
||||
|
||||
/**
|
||||
* Test specification for test_cond_signal
|
||||
*
|
||||
@@ -106,16 +137,16 @@ int test_cond_init_destroy(struct unit_module *m,
|
||||
* - Main Thread:
|
||||
* 1) Main thread resets the global variables test_code, test_cond
|
||||
* and test_data.
|
||||
* 2) Initialise the condition variabe by calling nvgpu_cond_init.
|
||||
* 2) Initialise the condition variable by calling nvgpu_cond_init.
|
||||
* 3) Return failure if the init function returns error.
|
||||
* 4) Copy the test args into global structure instance of unit_test_cond_data.
|
||||
* 4) Copy the test args into global instance of unit_test_cond_data.
|
||||
* 5) Reset global variables read_status and bcst_read_status to 0.
|
||||
* 6) Create the read thread.
|
||||
* 7) Cleanup the initialised cond variable and return failure if read thread
|
||||
* creation fails.
|
||||
* 7) Cleanup the initialised cond variable and return failure if read
|
||||
* thread creation fails.
|
||||
* 8) Create the write thread.
|
||||
* 9) Cleanup the initialised cond variable, cancel the read thread and return
|
||||
* failure if write thread creation fails.
|
||||
* 9) Cleanup the initialised cond variable, cancel the read thread and
|
||||
* return failure if write thread creation fails.
|
||||
* 10) Wait for both read and write thread to exit using pthread_join.
|
||||
* 11) Check for global variable read_status and return FAIL if the value
|
||||
* indicates an error.
|
||||
@@ -131,7 +162,8 @@ int test_cond_init_destroy(struct unit_module *m,
|
||||
* 5) Return from the thread handler.
|
||||
*
|
||||
* - Write Thread:
|
||||
* 1) Wait on global variable read_wait to be true before proceeding further.
|
||||
* 1) Wait on global variable read_wait to be true before proceeding
|
||||
* further.
|
||||
* 2) Update the global array test_code with a defined value.
|
||||
* 3) Reset read_wait to 0.
|
||||
* 4) Signal the condition variable.
|
||||
@@ -157,7 +189,7 @@ int test_cond_init_destroy(struct unit_module *m,
|
||||
*
|
||||
* e) Wait and Broadcast
|
||||
* In broadcast test cases an extra read thread is created by the main
|
||||
* thread. Both the read threads will get blocked on the codition variable.
|
||||
* thread. Both the read threads will get blocked on the condition variable.
|
||||
* The write thread has to broadcast the signal, which should bring both
|
||||
* the read threads out of blocked state. The main thread needs to wait for
|
||||
* the extra read thread also to exit in this case.
|
||||
@@ -185,10 +217,43 @@ int test_cond_init_destroy(struct unit_module *m,
|
||||
* Output:
|
||||
* All the tests return PASS if the condition variable is properly signalled
|
||||
* by the write thread and further verification of shared data shows a
|
||||
* succesful update from write thread with a predefined value.
|
||||
* successful update from write thread with a predefined value.
|
||||
* The tests return FAIL, if any of the above conditions are not met.
|
||||
*
|
||||
*/
|
||||
int test_cond_signal(struct unit_module *m,
|
||||
struct gk20a *g, void *args);
|
||||
|
||||
/**
|
||||
* Test specification for test_cond_timeout
|
||||
*
|
||||
* Description: Test time out for a condition variable wait.
|
||||
*
|
||||
* Test Type: Feature, Error injection
|
||||
*
|
||||
* Inputs:
|
||||
* 1) Global instance of struct nvgpu_cond.
|
||||
*
|
||||
* Steps:
|
||||
* 1) Initialize the condition variable.
|
||||
* 2) Call the function nvgpu_cond_timedwait with a timeout value.
|
||||
* 3) Check the return value from the function nvgpu_cond_timedwait. If the
|
||||
* return value is not ETIMEDOUT, unlock the mutex associated with the
|
||||
* condition variable then destroy the condition variable and return fail.
|
||||
* 4) If the return value is ETIMEDOUT, check the actual duration of timed
|
||||
* wait. If it is less than the requested timeout value, unlock the mutex
|
||||
* associated with the condition variable then destroy the condition
|
||||
* variable and return FAIL.
|
||||
* 5) Unlock the mutex associated with the condition variable then destroy the
|
||||
* condition variable and return pass.
|
||||
*
|
||||
* Output:
|
||||
* The test returns PASS if the nvgpu_cond_timedwait function returns
|
||||
* ETIMEDOUT error.
|
||||
* The test returns FAIL if the return value from nvgpu_cond_timedwait function
|
||||
* is not ETIMEDOUT.
|
||||
*
|
||||
*/
|
||||
int test_cond_timeout(struct unit_module *m,
|
||||
struct gk20a *g, void *args);
|
||||
#endif /* __UNIT_POSIX_COND_H__ */
|
||||
|
||||
Reference in New Issue
Block a user