Open source GPL/LGPL release

This commit is contained in:
svcmobrel-release
2025-12-19 15:25:44 -08:00
commit 9fc87a7ec7
2261 changed files with 576825 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = atomic.o
MODULE = atomic
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=atomic
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,28 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=atomic
NVGPU_UNIT_SRCS=atomic.c
ifneq ($(NV_BUILD_CONFIGURATION_OS_IS_QNX),1)
NVGPU_UNIT_SHARED_LIBRARIES += pthread
endif
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,255 @@
/*
* 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_INTERFACE_ATOMIC_H
#define UNIT_INTERFACE_ATOMIC_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-atomic
* @{
*
* Software Unit Test Specification for interface-atomic
*/
/**
* Test specification for: test_atomic_set_and_read
*
* Description: Test atomic set and read operations.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_set, nvgpu_atomic64_set,
* nvgpu_atomic_read, nvgpu_atomic64_read
*
* Input: struct atomic_test_args passed via the __args parameter.
*
* Steps:
* - Set the limit values for each atomic's size and read back to verify.
* - Loop through setting each bit in the atomic, reading each time to verify.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_set_and_read(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_atomic_arithmetic
*
* Description: Test arithemtic atomic operations inc, dec, add, sub and friends
* (except add_unless) single threaded for proper functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_inc, nvgpu_atomic64_inc,
* nvgpu_atomic_inc_return, nvgpu_atomic64_inc_return,
* nvgpu_atomic_inc_and_test, nvgpu_atomic64_inc_and_test,
* nvgpu_atomic_dec, nvgpu_atomic64_dec,
* nvgpu_atomic_dec_return, nvgpu_atomic64_dec_return,
* nvgpu_atomic_dec_and_test, nvgpu_atomic64_dec_and_test,
* nvgpu_atomic_add, nvgpu_atomic64_add,
* nvgpu_atomic_add_return, nvgpu_atomic64_add_return,
* nvgpu_atomic_sub, nvgpu_atomic64_sub,
* nvgpu_atomic_sub_return, nvgpu_atomic64_sub_return,
* nvgpu_atomic_sub_and_test, nvgpu_atomic64_sub_and_test,
* nvgpu_atomic_read, nvgpu_atomic64_read,
* nvgpu_atomic_set, nvgpu_atomic64_set
*
* Input: struct atomic_test_args passed via the __args parameter.
* For *_and_test ops, the args should make sure the loop traverses
* across 0 to test the "test" part.
*
* Steps:
* - Sets a start value from args.
* - Loops (iterations per args param).
* - Validates final result.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_arithmetic(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_atomic_arithmetic_threaded
*
* Description: Test atomic operations inc, dec, add, sub, cmpxchg, in threads
* to verify atomicity.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_cmpxchg, nvgpu_atomic64_cmpxchg,
* nvgpu_atomic_inc, nvgpu_atomic64_inc,
* nvgpu_atomic_inc_and_test, nvgpu_atomic64_inc_and_test,
* nvgpu_atomic_dec, nvgpu_atomic64_dec,
* nvgpu_atomic_dec_and_test, nvgpu_atomic64_dec_and_test,
* nvgpu_atomic_add, nvgpu_atomic64_add,
* nvgpu_atomic_add_return, nvgpu_atomic64_add_return,
* nvgpu_atomic_sub, nvgpu_atomic64_sub,
* nvgpu_atomic_sub_and_test, nvgpu_atomic64_sub_and_test,
* nvgpu_atomic_read, nvgpu_atomic64_read,
* nvgpu_atomic_set, nvgpu_atomic64_set,
* nvgpu_atomic_add_unless, nvgpu_atomic64_add_unless
*
* Input: struct atomic_test_args passed via the __args parameter.
*
* Steps:
* - Sets initial start value.
* - Kicks off threads to loop running ops.
* - When threads finish loops, verify values.
* - With the ops that have a return, save the final value for each thread and
* use that to try to ensure that the threads aren't executing sequentially.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_arithmetic_threaded(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_atomic_arithmetic_and_test_threaded
*
* Description: Test arithmetic *_and_test functions in threads to verify
* atomicity.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_inc_and_test, nvgpu_atomic64_inc_and_test,
* nvgpu_atomic_dec_and_test, nvgpu_atomic64_dec_and_test,
* nvgpu_atomic_sub_and_test, nvgpu_atomic64_sub_and_test,
* nvgpu_atomic_read, nvgpu_atomic64_read,
* nvgpu_atomic_set, nvgpu_atomic64_set
*
* Input: struct atomic_test_args passed via the __args parameter.
*
* Steps:
* - Set the atomic to a value to allow the arithmetic op to pass 0.
* - Start a lot of threads that will each execute the atomic op many times to
* ensure concurrency.
* - If the atomic op reports the value is zero, this iteration is recorded.
* - Check iteration count to make sure only 0 was observed exactly once.
* - Repeat above steps until reaching the input argument repeat_count or seeing
* a failure.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_arithmetic_and_test_threaded(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_atomic_xchg
*
* Description: Test xchg op single threaded for proper functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_xchg, nvgpu_atomic64_xchg,
* nvgpu_atomic_set, nvgpu_atomic64_set,
* nvgpu_atomic_read, nvgpu_atomic64_read
*
* Input: struct atomic_test_args passed via the __args parameter.
*
* Steps:
* - Loops calling xchg op with different values making sure the returned
* value is the last one written.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_xchg(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_atomic_xchg_threaded
*
* Description: Test atomic exchange operation with threads to test atomicity.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_xchg, nvgpu_atomic64_xchg,
* nvgpu_atomic_set, nvgpu_atomic64_set,
* nvgpu_atomic_read, nvgpu_atomic64_read
*
* Input: struct atomic_test_args passed via the __args parameter.
*
* Steps:
* - Set the atomic to a starting value.
* - Setup and start the exchange threads.
* - Setup includes setting each thread's "xchg_val" to its thread number.
* - When threads complete, loop through the thread's xchg_val and make sure
* each number is unique and someone still has the starting value.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_xchg_threaded(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_atomic_cmpxchg
*
* Description: Test cmpxchg single threaded for proper functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_cmpxchg, nvgpu_atomic64_cmpxchg,
* nvgpu_atomic_set, nvgpu_atomic64_set,
* nvgpu_atomic_read, nvgpu_atomic64_read
*
* Input: struct atomic_test_args passed via the __args parameter.
*
* Steps:
* - Loop calling cmpxchg. Alternating between matching and not matching.
* - Verify correct behavior for each call to the operation.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_cmpxchg(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_atomic_add_unless
*
* Description: Test add_unless op single threaded for proper functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_atomic_add_unless, nvgpu_atomic64_add_unless
*
* Input: struct atomic_test_args passed via the __args parameter.
*
* Steps:
* - Loop through calling the operation. Alternating whether the add should
* occur or not (i.e. changing the "unless" value).
* - Verify correct behavior for each operation.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_atomic_add_unless(struct unit_module *m,
struct gk20a *g, void *__args);
#endif /* UNIT_INTERFACE_ATOMIC_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = bit-utils.o
MODULE = bit-utils
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=bit-utils
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,24 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=bit-utils
NVGPU_UNIT_SRCS=bit-utils.c
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/utils.h>
#include "bit-utils.h"
int test_hi_lo(struct unit_module *m, struct gk20a *g, void *args)
{
u64 val_hi = 0xfedcba01;
u64 val_lo = 0x12345678;
u64 full_val = (val_hi << 32) | val_lo;
unit_assert(u64_hi32(full_val) == val_hi, return UNIT_FAIL);
unit_assert(u64_lo32(full_val) == val_lo, return UNIT_FAIL);
unit_assert(hi32_lo32_to_u64(val_hi, val_lo) == full_val,
return UNIT_FAIL);
return UNIT_SUCCESS;
}
int test_fields(struct unit_module *m, struct gk20a *g, void *args)
{
unit_assert(set_field(0U, 0x000ff000, 0x00055000) == 0x00055000,
return UNIT_FAIL);
unit_assert(set_field(0U, 0xffffffff, 0x00055000) == 0x00055000,
return UNIT_FAIL);
unit_assert(set_field(0xffffffff, 0xffffffff, 0x00055000) == 0x00055000,
return UNIT_FAIL);
unit_assert(set_field(0xffffffff, 0x000ff000, 0x00055000) == 0xfff55fff,
return UNIT_FAIL);
unit_assert(get_field(0U, 0xffffffff) == 0x0, return UNIT_FAIL);
unit_assert(get_field(0xffffffff, 0xffffffff) == 0xffffffff,
return UNIT_FAIL);
unit_assert(get_field(0xffffffff, 0x000ff000) == 0x000ff000,
return UNIT_FAIL);
return UNIT_SUCCESS;
}
struct unit_module_test bit_utils_tests[] = {
UNIT_TEST(hi_lo, test_hi_lo, NULL, 0),
UNIT_TEST(fields, test_fields, NULL, 0),
};
UNIT_MODULE(bit_utils, bit_utils_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_BIT_UTILS_H
#define UNIT_BIT_UTILS_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-bit-utils
* @{
*
* Software Unit Test Specification for common.utils.bit-utils
*/
/**
* Test specification for: test_hi_lo
*
* Description: Verify functionality of hi/lo bit-utils APIs.
*
* Test Type: Feature
*
* Targets: u64_hi32, u64_lo32, hi32_lo32_to_u64
*
* Input: None
*
* Steps:
* - Call u64_hi32 with a u64 value and verify the correct value is returned.
* - Call u64_lo32 with a u64 value and verify the correct value is returned.
* - Call hi32_lo32_to_u64 with two u32 values and verify the correct u64 value
* is returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_hi_lo(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_fields
*
* Description: Verify functionality of bit field bit-util APIs.
*
* Test Type: Feature
*
* Targets: set_field, get_field
*
* Input: None
*
* Steps:
* - Call set_field() with a variety of inputs and verify the correct value is
* returned.
* - Call get_field() with a variety of inputs and verify the correct value is
* returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_fields(struct unit_module *m, struct gk20a *g, void *args);
/**
* @}
*/
#endif /* UNIT_BIT_UTILS_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = kref.o
MODULE = kref
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=kref
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,24 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=kref
NVGPU_UNIT_SRCS=kref.c
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,210 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/kref.h>
#include "kref.h"
#define LOOP_COUNT 10
int release_count = 0;
static void test_ref_release(struct nvgpu_ref *ref)
{
release_count += 1;
}
int test_kref_init(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = 0;
struct nvgpu_ref test_ref;
nvgpu_ref_init(&test_ref);
ret = nvgpu_atomic_read(&test_ref.refcount);
if (ret != 1) {
unit_return_fail(m, "nvgpu_ref_init failure\n");
}
return UNIT_SUCCESS;
}
int test_kref_get(struct unit_module *m, struct gk20a *g, void *args)
{
int ret, loop;
struct nvgpu_ref test_ref;
nvgpu_ref_init(&test_ref);
for (loop = 1; loop < LOOP_COUNT; loop++) {
nvgpu_ref_get(&test_ref);
}
ret = nvgpu_atomic_read(&test_ref.refcount);
if (ret != LOOP_COUNT) {
unit_return_fail(m, "nvgpu_ref_get failure %d\n", ret);
}
return UNIT_SUCCESS;
}
int test_kref_get_unless(struct unit_module *m, struct gk20a *g, void *args)
{
int ret;
struct nvgpu_ref test_ref;
nvgpu_atomic_set(&test_ref.refcount, 0);
ret = nvgpu_atomic_read(&test_ref.refcount);
if (ret != 0) {
unit_return_fail(m, "nvgpu_ref set to 0 failure %d\n", ret);
}
ret = nvgpu_ref_get_unless_zero(&test_ref);
if (ret) {
unit_return_fail(m,
"nvgpu_ref_get_unless_zero failure %d\n", ret);
}
nvgpu_ref_init(&test_ref);
ret = nvgpu_ref_get_unless_zero(&test_ref);
if (!ret) {
unit_return_fail(m,
"nvgpu_ref_get_unless_zero failure\n");
}
return UNIT_SUCCESS;
}
int test_kref_put(struct unit_module *m, struct gk20a *g, void *args)
{
int ret, loop;
struct nvgpu_ref test_ref;
release_count = 0;
nvgpu_ref_init(&test_ref);
for (loop = 1; loop < LOOP_COUNT; loop++) {
nvgpu_ref_get(&test_ref);
}
ret = nvgpu_atomic_read(&test_ref.refcount);
if (ret != LOOP_COUNT) {
unit_return_fail(m, "nvgpu_ref_get failure %d\n", ret);
}
for (loop = 0; loop < LOOP_COUNT; loop++) {
nvgpu_ref_put(&test_ref, test_ref_release);
}
if (!release_count) {
unit_return_fail(m,
"release function not invoked\n");
} else if ((release_count > 1)) {
unit_return_fail(m,
"release function invoked more than once\n");
}
nvgpu_ref_get(&test_ref);
nvgpu_ref_put(&test_ref, NULL);
ret = nvgpu_atomic_read(&test_ref.refcount);
if (ret) {
unit_return_fail(m,
"nvgpu_ref_put with NULL callback failure %d\n", ret);
}
release_count = 0;
return UNIT_SUCCESS;
}
int test_kref_put_return(struct unit_module *m, struct gk20a *g, void *args)
{
int ret, loop;
struct nvgpu_ref test_ref;
release_count = 0;
nvgpu_ref_init(&test_ref);
for (loop = 1; loop < LOOP_COUNT; loop++) {
nvgpu_ref_get(&test_ref);
}
ret = nvgpu_atomic_read(&test_ref.refcount);
if (ret != LOOP_COUNT) {
unit_return_fail(m, "refcount not updated%d\n", ret);
}
for (loop = 0; loop < (LOOP_COUNT - 1); loop++) {
ret = nvgpu_ref_put_return(&test_ref, test_ref_release);
if (ret) {
unit_return_fail(m,
"nvgpu_ref_put_return failure\n");
}
}
ret = nvgpu_ref_put_return(&test_ref, test_ref_release);
if (!ret) {
unit_return_fail(m,
"nvgpu_ref_put_return failure\n");
}
if (!release_count) {
unit_return_fail(m,
"release function not invoked\n");
} else if ((release_count > 1)) {
unit_return_fail(m,
"release function invoked more than once\n");
}
release_count = 0;
nvgpu_ref_get(&test_ref);
ret = nvgpu_ref_put_return(&test_ref, NULL);
if (!ret) {
unit_return_fail(m,
"nvgpu_ref_put_return with NULL callback failure\n");
}
return UNIT_SUCCESS;
}
struct unit_module_test interface_kref_tests[] = {
UNIT_TEST(kref_init, test_kref_init, NULL, 0),
UNIT_TEST(kref_get, test_kref_get, NULL, 0),
UNIT_TEST(kref_get_unless, test_kref_get_unless, NULL, 0),
UNIT_TEST(kref_put, test_kref_put, NULL, 0),
UNIT_TEST(kref_put_return, test_kref_put_return, NULL, 0),
};
UNIT_MODULE(interface_kref, interface_kref_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,180 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_INTERFACE_KREF_H
#define UNIT_INTERFACE_KREF_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-kref
* @{
*
* Software Unit Test Specification for interface-kref
*/
/**
* Test specification for test_kref_init
*
* Description: Test the reference count initialization implementation.
*
* Test Type: Feature
*
* Targets: nvgpu_ref_init
*
* Input: None
*
* Steps:
* - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure.
* - Read back the refcount value and confirm the value is initialized to 1.
* Otherwise, return FAIL.
* - Return PASS.
*
* Output: Returns PASS if the refcount is initialized correctly, otherwise
* returns FAIL.
*/
int test_kref_init(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for test_kref_get
*
* Description: Test the reference get implementation.
*
* Test Type: Feature
*
* Targets: nvgpu_ref_get
*
* Input: None
*
* Steps:
* - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure.
* - Invoke the function nvgpu_ref_get in loop to increment the refcount value
* till LOOP_COUNT.
* - Read back the refcount value and confirm that the value returned is in
* sync with the number of times nvgpu_ref_get is called. Otherwise return
* FAIL.
* - Return PASS.
*
* Output: Returns PASS if the refcount is incremented correctly, otherwise
* returns FAIL.
*/
int test_kref_get(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for test_kref_get_unless
*
* Description: Test the reference get unless implementation.
*
* Test Type: Feature
*
* Targets: nvgpu_ref_get_unless_zero
*
* Input: None
*
* Steps:
* - Initialize the refcount value as 0 for nvgpu_ref struct.
* - Invoke function nvgpu_ref_get_unless_zero and confirm that the return
* value is 0. Otherwise return FAIL.
* - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure.
* - Invoke the function nvgpu_ref_get_unless_zero to increment the refcount
* value.
* - Check and confirm that the return value is not zero. Otherwise, return
* FAIL.
* - Return PASS.
*
* Output: Returns SUCCESS if the refcount is increased correctly according to
* the current value in refcount, otherwise return FAIL.
*/
int test_kref_get_unless(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for test_kref_put
*
* Description: Test the reference put implementation.
*
* Test Type: Feature
*
* Targets: nvgpu_ref_put
*
* Input: None
*
* Steps:
* - Initialize the release_count as 0.
* - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure.
* - Invoke the function nvgpu_ref_get in loop to increment the refcount value
* till LOOP_COUNT.
* - Read back the refcount value and confirm that the value returned is in
* sync with the number of times nvgpu_ref_get is called. Otherwise return
* FAIL.
* - Invoke the function nvgpu_ref_put in loop for LOOP_COUNT times to
* decrement the refcount value to 0.
* - Check the value of release_count value which is incremented in the
* release callback function to confirm that the release callback function
* is invoked and invoked only once. Otherwise return FAIL.
* - Invoke the function nvgpu_ref_get to increment the refcount value.
* - Invoke the function nvgpu_ref_put with callback as NULL.
* - Read back the refcount value and confirm that the value is reset to 0.
* Otherwise return FAIL.
* - Return PASS.
*
* Output: Returns SUCCESS if the refcerence is released correctly, otherwise
* return FAIL.
*/
int test_kref_put(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for test_kref_put_return
*
* Description: Test the reference put return implementation.
*
* Test Type: Feature
*
* Targets: nvgpu_ref_put_return
*
* Input: None
*
* Steps:
* - Initialize the release_count as 0.
* - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure.
* - Invoke the function nvgpu_ref_get in loop to increment the refcount value.
* - Read back the refcount value and confirm that the value returned is in
* sync with the number of times nvgpu_ref_get is called. Otherwise return
* FAIL.
* - Invoke the function nvgpu_ref_put in loop for (LOOP_COUNT - 1) to
* decrement the refcount value and confirm that the return value is always
* zero. Otherwise return FAIL.
* - Invoke the function nvgpu_ref_put once more and confirm that the return
* value is equal to one. Otherwise return FAIL.
* - Check the value of release_count value which is incremented in the
* release callback function to confirm that the release callback function
* is invoked and invoked only once. Otherwise return FAIL.
* - Invoke the function nvgpu_ref_get to increment the refcount value.
* - Invoke the function nvgpu_ref_put_return with callback as NULL.
* - Check the return value and return FAIL if it is equal to zero.
* - Return PASS.
*
* Output: Returns SUCCESS if the refcount is initialized correctly, otherwise
* return FAIL.
*/
int test_kref_put_return(struct unit_module *m, struct gk20a *g, void *__args);
#endif /* UNIT_INTERFACE_KREF_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2018, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = list.o
MODULE = list
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=list
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=list
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2018-2019, 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/list.h>
#include "list.h"
#define ELEMENTS 10
/* Simple list holding a single int value */
struct integer_list {
int value;
struct nvgpu_list_node list;
};
static inline struct integer_list *
integer_list_from_list(struct nvgpu_list_node *node)
{
return (struct integer_list *)
((uintptr_t)node - offsetof(struct integer_list, list));
};
/*
* Count the number of elements inside an integer_list
*/
static int list_count(struct nvgpu_list_node *head)
{
int count = 0;
struct integer_list *pos;
nvgpu_list_for_each_entry(pos, head, integer_list, list) {
count++;
}
return count;
}
/*
* Add "count" consecutive elements to the list. Depending on the value of
* "add_to_tail", the elements will be added to the head or the tail.
*/
static int add_consecutive_elements(struct nvgpu_list_node *head, int count,
bool add_to_tail)
{
int i;
int list_elements = list_count(head);
for (i = 0; i < count; i++) {
struct integer_list *node = malloc(sizeof(struct integer_list));
if (node == NULL) {
return -ENOMEM;
}
node->value = list_elements+i+1;
if (add_to_tail) {
nvgpu_list_add_tail(&node->list, head);
} else {
nvgpu_list_add(&node->list, head);
}
}
return 0;
}
/*
* Delete "count" consecutive elements starting from head.
*/
static int del_consecutive_elements(struct nvgpu_list_node *head, int count)
{
int i;
struct integer_list *pos;
for (i = 0; i < count; i++) {
if (nvgpu_list_empty(head)) {
return -ENOMEM;
}
pos = nvgpu_list_first_entry(head, integer_list, list);
nvgpu_list_del(&pos->list);
free(pos);
}
return 0;
}
/* Initialize the list and add some elements to it. */
static int init_list_elements(struct unit_module *m,
struct nvgpu_list_node *head, int count, bool add_to_tail)
{
nvgpu_init_list_node(head);
if (!nvgpu_list_empty(head)) {
unit_return_fail(m, "List should be empty");
}
if (add_consecutive_elements(head, count, add_to_tail) != 0) {
unit_return_fail(m, "Error adding elements");
}
if (nvgpu_list_empty(head)) {
unit_return_fail(m, "List should not be empty");
}
return 0;
}
int test_list_add(struct unit_module *m, struct gk20a *g, void *__args)
{
struct integer_list *pos;
int i;
struct nvgpu_list_node head;
bool tail_case = (bool) __args;
if (init_list_elements(m, &head, ELEMENTS, tail_case) != 0) {
return UNIT_FAIL;
}
i = tail_case ? 1 : ELEMENTS;
nvgpu_list_for_each_entry(pos, &head, integer_list, list) {
if (i != pos->value) {
unit_return_fail(m, "Incorrect value in list: %d/%d",
i, pos->value);
}
tail_case ? i++ : i--;
}
if (del_consecutive_elements(&head, ELEMENTS) != 0) {
unit_return_fail(m, "Could not delete all elements");
}
return UNIT_SUCCESS;
}
int test_list_move(struct unit_module *m, struct gk20a *g, void *__args)
{
struct integer_list *pos;
int i;
struct nvgpu_list_node head;
if (init_list_elements(m, &head, ELEMENTS, false) != 0) {
return UNIT_FAIL;
}
/*
* Add an extra element, but at the tail. Now the list is not ordered
* anymore
*/
if (add_consecutive_elements(&head, 1, true) != 0) {
unit_return_fail(m, "Error adding elements");
}
/*
* Move the extra element from the tail to the head so that the list
* is now ordered.
*/
pos = nvgpu_list_last_entry(&head, integer_list, list);
nvgpu_list_move(&pos->list, &head);
i = ELEMENTS + 1;
/* Now the list should be ordered */
nvgpu_list_for_each_entry(pos, &head, integer_list, list) {
if (i != pos->value) {
unit_return_fail(m, "Incorrect value in list: %d/%d",
i, pos->value);
}
i--;
}
if (del_consecutive_elements(&head, ELEMENTS) != 0) {
unit_return_fail(m, "Could not delete all elements");
}
return UNIT_SUCCESS;
}
int test_list_replace(struct unit_module *m, struct gk20a *g, void *__args)
{
struct integer_list *pos, *new_elem;
struct nvgpu_list_node head;
if (init_list_elements(m, &head, ELEMENTS, false) != 0) {
return UNIT_FAIL;
}
pos = nvgpu_list_last_entry(&head, integer_list, list);
new_elem = malloc(sizeof(struct integer_list));
if (new_elem == NULL) {
unit_return_fail(m, "Error creating new element");
}
new_elem->value = ELEMENTS * 2; /* Value is irrelevant */
nvgpu_list_replace_init(&pos->list, &new_elem->list);
/* The old element is out of the list and can now be freed */
free(pos);
pos = nvgpu_list_last_entry(&head, integer_list, list);
if (pos != new_elem) {
unit_return_fail(m, "Replace operation failed.");
}
if (del_consecutive_elements(&head, ELEMENTS) != 0) {
unit_return_fail(m, "Could not delete all elements");
}
return UNIT_SUCCESS;
}
struct unit_module_test list_tests[] = {
UNIT_TEST(list_all_head, test_list_add, (void *) false, 0),
UNIT_TEST(list_all_tail, test_list_add, (void *) true, 0),
UNIT_TEST(list_move, test_list_move, NULL, 0),
UNIT_TEST(list_replace, test_list_replace, NULL, 0),
};
UNIT_MODULE(interface_list, list_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_LIST_H
#define UNIT_LIST_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-list
* @{
*
* Software Unit Test Specification for interface.list
*/
/**
* Test specification for: test_list_add
*
* Description: Test case to verify that elements get added and stay in the
* right order.
*
* Test Type: Feature
*
* Targets: nvgpu_init_list_node, nvgpu_list_empty, nvgpu_list_add_tail,
* nvgpu_list_add, nvgpu_list_del
*
* Input: __args is a boolean to indicate if adding to the head (false) or to
* the tail (true)
*
* Steps:
* - Create a test list with a known number of elements of consecutive values.
* - For each element in the list, ensure it is consecutive with the previous
* one (ascending if adding to head, descending if adding to tail).
* - Delete all known elements from the list and ensure the resulting list
* is empty.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_list_add(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_list_move
*
* Description: Test case to verify that elements get added and stay in the
* right order.
*
* Test Type: Feature
*
* Targets: nvgpu_init_list_node, nvgpu_list_empty, nvgpu_list_add_tail,
* nvgpu_list_add, nvgpu_list_move, nvgpu_list_del
*
* Input: None
*
* Steps:
* - Create a test list with a known number of elements of consecutive values.
* - Add an extra element to the tail so that the list is not ordered anymore.
* - Move the last element to the head.
* - Ensure the list is now ordered.
* - Delete all known elements from the list and ensure the resulting list
* is empty.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_list_move(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_list_replace
*
* Description: Test case to test the replace operation by replacing the last
* node by a new one.
*
* Test Type: Feature
*
* Targets: nvgpu_init_list_node, nvgpu_list_empty, nvgpu_list_add_tail,
* nvgpu_list_add, nvgpu_list_replace_init, nvgpu_list_del
*
* Input: None
*
* Steps:
* - Create a test list with a known number of elements of consecutive values.
* - Create a new node.
* - Get the last element of the list and replace it by the new node.
* - Ensure the last element of the list is indeed the new node.
* - Delete all known elements from the list and ensure the resulting list
* is empty.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_list_replace(struct unit_module *m, struct gk20a *g, void *__args);
/** }@ */
#endif /* UNIT_LIST_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2018-2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = lock.o
MODULE = lock
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=lock
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,39 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018-2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=lock
ifneq ($(NV_BUILD_CONFIGURATION_OS_IS_QNX),1)
NVGPU_UNIT_SHARED_LIBRARIES += pthread
endif
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,300 @@
/*
* 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unit/io.h>
#include <unit/unit.h>
#include <unit/unit-requirement-ids.h>
#include <nvgpu/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/lock.h>
#include <pthread.h>
#include <unistd.h>
#include "lock.h"
/* Parameter structure to pass to worker threads */
struct worker_parameters {
u64 type;
struct nvgpu_mutex *mutex;
struct nvgpu_spinlock *lock;
struct nvgpu_raw_spinlock *raw_lock;
};
int worker_sem = -1;
/* Mutex for atomicity of operations on "worker_sem" */
pthread_mutex_t nvgpu_sem_mutex = PTHREAD_MUTEX_INITIALIZER;
bool test_shared_flag;
static void nvgpu_sem_init(int *sem)
{
(*sem) = -1;
pthread_mutex_init(&nvgpu_sem_mutex, NULL);
return;
}
static void nvgpu_sem_post(int *sem)
{
pthread_mutex_lock(&nvgpu_sem_mutex);
(*sem) = (*sem) + 1;
pthread_mutex_unlock(&nvgpu_sem_mutex);
return;
}
static void nvgpu_sem_wait(int *sem)
{
pthread_mutex_lock(&nvgpu_sem_mutex);
while ((*sem) == -1) {
pthread_mutex_unlock(&nvgpu_sem_mutex);
/* Wait for 1 msec */
usleep(1000);
pthread_mutex_lock(&nvgpu_sem_mutex);
}
(*sem) = (*sem) - 1;
pthread_mutex_unlock(&nvgpu_sem_mutex);
return;
}
int test_mutex_init(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_mutex mutex;
nvgpu_mutex_init(&mutex);
nvgpu_mutex_destroy(&mutex);
return UNIT_SUCCESS;
}
int test_mutex_tryacquire(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_mutex mutex;
int status;
nvgpu_mutex_init(&mutex);
nvgpu_mutex_acquire(&mutex);
status = nvgpu_mutex_tryacquire(&mutex);
if (status == 1) {
unit_return_fail(m, "tryacquire did not fail as expected: %d\n",
status);
}
nvgpu_mutex_release(&mutex);
status = nvgpu_mutex_tryacquire(&mutex);
if (status != 1) {
unit_return_fail(m,
"tryacquire did not succeed as expected: %d\n", status);
}
nvgpu_mutex_release(&mutex);
nvgpu_mutex_destroy(&mutex);
return UNIT_SUCCESS;
}
/*
* Worker function to be used in a separate thread to test acquire of one of
* the supported lock types, provided as an argument.
*/
static void *lock_worker(void *args)
{
struct worker_parameters *params = (struct worker_parameters *) args;
/* Signal main testing function that the worker thread has started. */
nvgpu_sem_post(&worker_sem);
/*
* Lock should already be held by the main test function, so execution
* should block here.
*/
switch (params->type) {
case TYPE_MUTEX:
nvgpu_mutex_acquire(params->mutex);
break;
case TYPE_SPINLOCK:
nvgpu_spinlock_acquire(params->lock);
break;
case TYPE_RAW_SPINLOCK:
nvgpu_raw_spinlock_acquire(params->raw_lock);
break;
default:
break;
}
/*
* Update the shared_flag to indicate that the spinlock_acquire
* succeeded and signal the main thread.
*/
test_shared_flag = true;
nvgpu_sem_post(&worker_sem);
/* Cleanup */
switch (params->type) {
case TYPE_MUTEX:
nvgpu_mutex_release(params->mutex);
break;
case TYPE_SPINLOCK:
nvgpu_spinlock_release(params->lock);
break;
case TYPE_RAW_SPINLOCK:
nvgpu_raw_spinlock_release(params->raw_lock);
break;
default:
break;
}
return NULL;
}
/*
* Test to verify the behavior of mutex, regular and raw spinlocks acquire and
* release functions.
* The "args" argument is an int indicating the lock type.
*/
int test_lock_acquire_release(struct unit_module *m, struct gk20a *g,
void *args)
{
struct nvgpu_mutex mutex;
struct nvgpu_spinlock lock;
struct nvgpu_raw_spinlock raw_lock;
pthread_t worker_thread;
struct worker_parameters worker_params;
u64 type = (u64) args;
int result = UNIT_FAIL;
worker_params.type = type;
switch (type) {
case TYPE_MUTEX:
nvgpu_mutex_init(&mutex);
worker_params.mutex = &mutex;
break;
case TYPE_SPINLOCK:
nvgpu_spinlock_init(&lock);
worker_params.lock = &lock;
break;
case TYPE_RAW_SPINLOCK:
nvgpu_raw_spinlock_init(&raw_lock);
worker_params.raw_lock = &raw_lock;
break;
default:
unit_return_fail(m, "Unexpected lock type.\n");
break;
}
/*
* The semaphore is used to synchronize things when needed between the
* current thread and the worker thread
* (*_acquire_release_worker)
*/
nvgpu_sem_init(&worker_sem);
test_shared_flag = false;
/*
* Acquire the lock so that the worker thread will block when it tries
* to acquire it too.
*/
switch (type) {
case TYPE_MUTEX:
nvgpu_mutex_acquire(&mutex);
break;
case TYPE_SPINLOCK:
nvgpu_spinlock_acquire(&lock);
break;
case TYPE_RAW_SPINLOCK:
nvgpu_raw_spinlock_acquire(&raw_lock);
break;
default:
break;
}
/* Start the thread and wait for its signal */
pthread_create(&worker_thread, NULL, lock_worker,
(void *) &worker_params);
nvgpu_sem_wait(&worker_sem);
/*
* Worker thread is initialized and running. It should be waiting on the
* lock, if not (i.e. the flag was updated) then it's a failure
*/
if (test_shared_flag) {
unit_err(m, "Worker thread did not block on lock\n");
goto cleanup;
}
/*
* If the flag was not updated, release the lock and check that the
* flag was updated this time
*/
switch (type) {
case TYPE_MUTEX:
nvgpu_mutex_release(&mutex);
break;
case TYPE_SPINLOCK:
nvgpu_spinlock_release(&lock);
break;
case TYPE_RAW_SPINLOCK:
nvgpu_raw_spinlock_release(&raw_lock);
break;
default:
break;
}
nvgpu_sem_wait(&worker_sem);
if (!test_shared_flag) {
unit_err(m, "Lock did not get released in worker thread\n");
goto cleanup;
}
result = UNIT_SUCCESS;
cleanup:
pthread_join(worker_thread, NULL);
if (type == TYPE_MUTEX) {
nvgpu_mutex_destroy(&mutex);
}
return result;
}
struct unit_module_test interface_lock_tests[] = {
UNIT_TEST(mutex_init, test_mutex_init, NULL, 0),
UNIT_TEST(mutex_acquire_release, test_lock_acquire_release,
(u64 *) 0, 0),
UNIT_TEST(spinlock_acquire_release, test_lock_acquire_release,
(u64 *) 1, 0),
UNIT_TEST(raw_spinlock_acquire_release, test_lock_acquire_release,
(u64 *) 2, 0),
UNIT_TEST(mutex_tryacquire, test_mutex_tryacquire, NULL, 0),
};
UNIT_MODULE(interface_lock, interface_lock_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,131 @@
/*
* 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_LOCK_H
#define UNIT_LOCK_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-lock
* @{
*
* Software Unit Test Specification for interface.lock
*/
/**
* \name Lock Types
* There are 3 types of locks supported by this unit test, defined as below.
*/
/** @{ */
#define TYPE_MUTEX 0
#define TYPE_SPINLOCK 1
#define TYPE_RAW_SPINLOCK 2
/** @} */
/**
* Test specification for: test_mutex_init
*
* Description: Simple test to check mutex init routine.
*
* Test Type: Feature
*
* Targets: nvgpu_mutex_init, nvgpu_mutex_destroy
*
* Input: None
*
* Steps:
* - Initialize a mutex via the nvgpu_mutex_init function.
* - Destroy the mutex via the nvgpu_mutex_destroy function.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_mutex_init(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_mutex_tryacquire
*
* Description: Test to verify the behavior of mutex tryacquire function.
*
* Test Type: Feature
*
* Targets: nvgpu_mutex_init, nvgpu_mutex_acquire, nvgpu_mutex_tryacquire,
* nvgpu_mutex_release, nvgpu_mutex_destroy,
* nvgpu_posix_lock_try_acquire, nvgpu_posix_lock_release
*
* Input: None
*
* Steps:
* - Initialize a mutex via the nvgpu_mutex_init function.
* - Acquire the mutex.
* - Perform a nvgpu_mutex_tryacquire on the mutex and ensure that the operation
* returned a failure code.
* - Release the mutex.
* - Perform a nvgpu_mutex_tryacquire again and ensure that the operation
* succeeded.
* - Release and destroy the mutex.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_mutex_tryacquire(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_lock_acquire_release
*
* Description: Test to verify the behavior of mutex, regular and raw spinlocks
* acquire and release functions. For this purpose, there are 2 threads
* involved: the regular main thread, and a worker thread.
*
* Test Type: Feature
*
* Targets: nvgpu_mutex_init, nvgpu_spinlock_init, nvgpu_raw_spinlock_init,
* nvgpu_mutex_acquire, nvgpu_spinlock_acquire,
* nvgpu_raw_spinlock_acquire, nvgpu_mutex_release,
* nvgpu_spinlock_release, nvgpu_raw_spinlock_release,
* nvgpu_posix_lock_acquire, nvgpu_posix_lock_release
*
* Input: @param args [in] Type of lock as defined by TYPE_* macros.
*
* Steps:
* - Initialize the lock using the corresponding init function.
* - Create a semaphore \a worker_sem and set the \a test_shared_flag to false.
* - Acquire the lock using its corresponding acquire function.
* - Create the worker thread and wait for it to signal that it is ready thanks
* to the \a worker_sem.
* - The worker thread then blocks trying to acquire the lock.
* - The main thread then releases the lock and wait for a signal from the
* worker thread via \a worker_sem.
* - The worker thread should now be able to acquire the lock and update the
* \a test_shared_flag.
* - The main thread ensures that the \a test_shared_flag was updated.
* - Release and destroy the lock and the worker thread.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_lock_acquire_release(struct unit_module *m, struct gk20a *g,
void *args);
/** }@ */
#endif /* UNIT_LOCK_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = nvgpu_gk20a.o
MODULE = nvgpu_gk20a
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_gk20a
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,24 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_gk20a
NVGPU_UNIT_SRCS=nvgpu_gk20a.c
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include "nvgpu_gk20a.h"
int test_get_poll_timeout(struct unit_module *m, struct gk20a *g, void *args)
{
const u32 default_timeout = 123456;
g->poll_timeout_default = default_timeout;
unit_assert(nvgpu_get_poll_timeout(g) == default_timeout,
return UNIT_FAIL);
return UNIT_SUCCESS;
}
struct unit_module_test nvgpu_gk20a_tests[] = {
UNIT_TEST(get_poll_timeout, test_get_poll_timeout, NULL, 0),
};
UNIT_MODULE(nvgpu_gk20a, nvgpu_gk20a_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_NVGPU_GK20A_H
#define UNIT_NVGPU_GK20A_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-nvgpu-gk20a
* @{
*
* Software Unit Test Specification for common.nvgpu.gk20a
*/
/**
* Test specification for: test_get_poll_timeout
*
* Description: Verify functionality nvgpu_get_poll_timeout().
*
* Test Type: Feature
*
* Targets: nvgpu_get_poll_timeout, nvgpu_is_timeouts_enabled
*
* Input: None
*
* Steps:
* - Call nvgpu_get_poll_timeout and verify the correct value is returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_get_poll_timeout(struct unit_module *m, struct gk20a *g, void *args);
/**
* @}
*/
#endif /* UNIT_NVGPU_GK20A_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = rbtree.o
MODULE = rbtree
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=rbtree
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=rbtree
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,548 @@
/*
* Copyright (c) 2019, 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unit/io.h>
#include <unit/unit.h>
#include <unit/core.h>
#include <nvgpu/rbtree.h>
#include <stdlib.h>
#include "rbtree.h"
struct nvgpu_rbtree_node *elements[INITIAL_ELEMENTS];
/*
* Helper function to ensure a given tree satisfies all the properties to be
* considered a red-black binary tree. That is:
* 1. Every node is either red or black: implied since color is a bool with only
* two possible values.
* 2. The root is black: checked by the function below.
* 3. Every leaf is black: implied since all leaves are NULL.
* 4. If a node is red, then both its children have to be black: checked by the
* function below.
* 5. All simple paths from a node to its descendant leaves must contain the
* same number of black nodes: checked by the function below.
*
* So only properties 2, 4 and 5 need to be checked.
*
* Returns either:
* - a negative value in case of error
* - the number of black nodes to leaves (which is the black height of the tree
* when ran from the root).
*/
static int check_rbtree(struct unit_module *m, struct nvgpu_rbtree_node *node)
{
int left_black_count, right_black_count;
int black_count = 0;
if (node == NULL) {
/* This is a leaf, so black count is 1 */
return 1;
}
/* Check property 2 (root is black) */
if ((node->parent == NULL) && (node->is_red)) {
unit_err(m, "check_rbtree: root is red\n");
return -1;
}
/* Check property 4 (if red node, children must be black) */
if (node->is_red) {
/*
* If left or right is NULL then it is a leaf which is
* implicitly black
*/
if ((node->left != NULL) && (node->left->is_red)) {
unit_err(m,
"check_rbtree: l_child of red parent is also red\n");
return -1;
}
if ((node->right != NULL) && (node->right->is_red)) {
unit_err(m,
"check_rbtree: r_child of red parent is also red\n");
return -1;
}
}
/* Count black nodes */
if (!node->is_red) {
black_count = 1;
}
/*
* Check property 5 (descendant leaves must have the same number of
* black nodes)
* Start by recursively checking the height of the left and right
* sub-trees.
*/
left_black_count = check_rbtree(m, node->left);
right_black_count = check_rbtree(m, node->right);
if ((left_black_count == -1) || (right_black_count == -1)) {
/* There was an error in one of the subtrees, propagate it */
return -1;
}
if (left_black_count != right_black_count) {
unit_err(m, "check_rbtree: mismatch between left and right\n");
return -1;
}
return left_black_count + black_count;
}
/*
* Helper function to insert elements into a tree using the initial_key_start
* values.
*/
static int fill_test_tree(struct unit_module *m,
struct nvgpu_rbtree_node **root)
{
int i;
for (i = 0; i < INITIAL_ELEMENTS; i++) {
elements[i] = (struct nvgpu_rbtree_node *)
malloc(sizeof(struct nvgpu_rbtree_node));
elements[i]->key_start = initial_key_start[i];
elements[i]->key_end = initial_key_start[i]+RANGE_SIZE;
nvgpu_rbtree_insert(elements[i], root);
}
return UNIT_SUCCESS;
}
/*
* Helper function to free the test nodes of the tree.
*/
static void free_test_tree(struct unit_module *m,
struct nvgpu_rbtree_node *root)
{
int i;
for (i = 0; i < INITIAL_ELEMENTS; i++) {
free(elements[i]);
}
/* No need to explicitly free the root as it was one of the elements */
}
int test_insert(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_rbtree_node *root = NULL;
struct nvgpu_rbtree_node *node1, *node2 = NULL;
int status = UNIT_FAIL;
fill_test_tree(m, &root);
if (check_rbtree(m, root) < 0) {
goto free_tree;
}
node1 = (struct nvgpu_rbtree_node *)
malloc(sizeof(struct nvgpu_rbtree_node));
node1->key_start = RED_BLACK_VIOLATION_1;
node1->key_end = RED_BLACK_VIOLATION_1+RANGE_SIZE;
nvgpu_rbtree_insert(node1, &root);
node2 = (struct nvgpu_rbtree_node *)
malloc(sizeof(struct nvgpu_rbtree_node));
node2->key_start = RED_BLACK_VIOLATION_2;
node2->key_end = RED_BLACK_VIOLATION_2+RANGE_SIZE;
nvgpu_rbtree_insert(node2, &root);
if (check_rbtree(m, root) < 0) {
goto free_nodes;
}
status = UNIT_SUCCESS;
free_nodes:
free(node1);
free(node2);
free_tree:
free_test_tree(m, root);
return status;
}
int test_unlink(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_rbtree_node *root = NULL;
struct nvgpu_rbtree_node *result = NULL;
int status = UNIT_FAIL;
bool duplicate_handled = false;
u64 key_start_search;
int i;
fill_test_tree(m, &root);
for (i = 0; i < INITIAL_ELEMENTS; i++) {
/*
* Search for a node from values in the initial_key_start table.
*/
key_start_search = initial_key_start[i];
if ((key_start_search == DUPLICATE_VALUE) &&
(!duplicate_handled)) {
duplicate_handled = true;
continue;
}
nvgpu_rbtree_search(key_start_search, &result, root);
if (result == NULL) {
unit_err(m, "Search failed for key_start=%lld\n",
key_start_search);
goto cleanup;
} else {
if (verbose_lvl(m) > 0) {
unit_info(m, "Found node with key_start=%lld\n",
result->key_start);
}
}
/*
* Unlink will simply remove the node from the tree. It will not
* free the resources. It will be done at the end of this
* function.
*/
nvgpu_rbtree_unlink(result, &root);
/* Make sure the node was actually removed */
nvgpu_rbtree_search(key_start_search, &result, root);
if (result != NULL) {
unit_err(m, "Unlink failed, node still exists\n");
goto cleanup;
} else {
if (verbose_lvl(m) > 0) {
unit_info(m, "Node was removed as expected\n");
}
}
}
status = UNIT_SUCCESS;
cleanup:
free_test_tree(m, root);
return status;
}
int test_search(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_rbtree_node *root = NULL;
struct nvgpu_rbtree_node *result1, *result2 = NULL;
int status = UNIT_FAIL;
u64 key_start_search = SEARCH_KEY;
fill_test_tree(m, &root);
/* Search with a NULL root should not crash and keep result as NULL */
nvgpu_rbtree_search(key_start_search, &result1, NULL);
if (result1 != NULL) {
unit_err(m, "Search did not fail as expected\n");
goto cleanup;
}
/* Same thing with the range_search operation */
nvgpu_rbtree_range_search(key_start_search, &result2, NULL);
if (result1 != NULL) {
unit_err(m, "Range search did not fail as expected\n");
goto cleanup;
}
/* Now search for a real value */
if (verbose_lvl(m) > 0) {
unit_info(m, "Searching for key_start=%lld\n",
key_start_search);
}
nvgpu_rbtree_search(key_start_search, &result1, root);
if (result1 == NULL) {
unit_err(m, "Search failed\n");
goto cleanup;
} else if (verbose_lvl(m) > 0) {
unit_info(m, "Found node with key_start=%lld key_end=%lld\n",
result1->key_start, result1->key_end);
}
/*
* Now do a range search by just incrementing key_start_search by 1
* which should yield the exact same result as the previous search
* (since it will fall in the same range)
*/
key_start_search++;
if (verbose_lvl(m) > 0) {
unit_info(m, "Range searching for key=%lld\n",
key_start_search);
}
nvgpu_rbtree_range_search(key_start_search, &result2, root);
if (result2 == NULL) {
unit_err(m, "Range search failed\n");
goto cleanup;
} else if (result1 != result2) {
unit_err(m, "Range search did not find the expected result\n");
goto cleanup;
} else if (verbose_lvl(m) > 0) {
unit_info(m, "Found node with key_start=%lld key_end=%lld\n",
result1->key_start, result1->key_end);
}
status = UNIT_SUCCESS;
cleanup:
free_test_tree(m, root);
return status;
}
int test_enum(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_rbtree_node *root = NULL;
struct nvgpu_rbtree_node *node = NULL;
int status = UNIT_FAIL;
u64 key_start;
int i;
fill_test_tree(m, &root);
/* Enum with a NULL root should not crash and keep result as NULL */
nvgpu_rbtree_enum_start(0, &node, NULL);
if (node != NULL) {
unit_err(m, "Enum did not fail as expected (NULL root)\n");
goto cleanup;
}
/* Enum all the nodes we know are in the tree */
for (i = 0; i < INITIAL_ELEMENTS; i++) {
key_start = initial_key_start[i];
nvgpu_rbtree_enum_start(key_start, &node, root);
if (node->key_start != key_start) {
unit_err(m, "Enum mismatch\n");
goto cleanup;
}
}
/* If the key_start does not exist, enum should return a NULL node */
nvgpu_rbtree_enum_start(INVALID_KEY_START, &node, root);
if (node != NULL) {
unit_err(m, "Enum did not fail as expected: wrong key_start\n");
goto cleanup;
}
status = UNIT_SUCCESS;
cleanup:
free_test_tree(m, root);
return status;
}
int test_enum_next(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_rbtree_node *root = NULL;
struct nvgpu_rbtree_node *node = NULL;
int status = UNIT_FAIL;
u64 prev_key_start;
fill_test_tree(m, &root);
/* Enum with a NULL root should not crash and keep result as NULL */
nvgpu_rbtree_enum_next(&node, NULL);
if (node != NULL) {
unit_err(m, "Enum_next did not fail as expected (NULL root)\n");
goto cleanup;
}
/*
* The tree is balanced and we know there are INITIAL_ELEMENTS inside.
* Enumerate the next key_start value from root.
*/
node = root;
prev_key_start = node->key_start;
while (node != NULL) {
nvgpu_rbtree_enum_next(&node, root);
if (node != NULL) {
if (verbose_lvl(m) > 0) {
unit_info(m, "Node has key_start=%lld\n",
node->key_start);
}
if (node->key_start < prev_key_start) {
unit_err(m, "Enum_next returned a low value\n");
goto cleanup;
}
prev_key_start = node->key_start;
}
}
/* For branch coverage, test some error handling. */
node = NULL;
nvgpu_rbtree_enum_next(&node, root);
nvgpu_rbtree_enum_next(&node, NULL);
status = UNIT_SUCCESS;
cleanup:
free_test_tree(m, root);
return status;
}
int test_search_less(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_rbtree_node *root = NULL;
struct nvgpu_rbtree_node *result;
int status = UNIT_FAIL;
u64 key_start_search;
fill_test_tree(m, &root);
/*
* The tree is balanced, so the range in the root should be in the
* middle of the values, so searching for that value will guarantee
* a result.
*/
key_start_search = root->key_start;
nvgpu_rbtree_less_than_search(key_start_search, &result, root);
if (result == NULL) {
unit_err(m, "less_than_search unexpectedly failed\n");
goto cleanup;
}
if (result->key_start >= key_start_search) {
unit_err(m, "less_than_search returned a wrong result\n");
goto cleanup;
}
status = UNIT_SUCCESS;
cleanup:
free_test_tree(m, root);
return status;
}
int test_unlink_corner_cases(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_rbtree_node *root = NULL;
u64 more_key_start[] = {0x1000, 0x61000, 0x79000, 0x7d000, 0x7f000,
0x80000, 0x91000, 0x81000, 0x71000, 0x99000, 0x9d000, 0xa0000,
0x500, 0x600, 0x700, 0x800, 0x900, 0xa000, 0xb000, 0xc000,
0xd000, 0xe000, 0xf000};
u64 num_elems = sizeof(more_key_start) / sizeof(u64);
struct nvgpu_rbtree_node **more_elements =
malloc(sizeof(struct nvgpu_rbtree_node *)*num_elems);
u64 i;
fill_test_tree(m, &root);
/*
* Add extra nodes to create a much more complicated tree that will
* allow targeting specific conditions when unlinking those nodes.
* Even though the unlinking of some of those nodes have no direct
* impact on line or branch coverage, their presence is needed to create
* the corner cases we need.
*/
for (i = 0; i < num_elems; i++) {
more_elements[i] = (struct nvgpu_rbtree_node *)
malloc(sizeof(struct nvgpu_rbtree_node));
more_elements[i]->key_start = more_key_start[i];
more_elements[i]->key_end = more_key_start[i]+RANGE_SIZE;
nvgpu_rbtree_insert(more_elements[i], &root);
}
/* No impact on coverage */
nvgpu_rbtree_unlink(more_elements[0], &root);
/*
* Targets some conditions when removing a node on the left and the
* right needs to become red.
*/
nvgpu_rbtree_unlink(more_elements[1], &root);
/* No impact on coverage */
nvgpu_rbtree_unlink(more_elements[2], &root);
/*
* Targets some conditions when removing a node on the left and the
* right is NULL.
*/
nvgpu_rbtree_unlink(more_elements[3], &root);
/* No impact on coverage */
nvgpu_rbtree_unlink(more_elements[4], &root);
/*
* Targets some conditions when removing a node on the left and the
* right node is red. This requires rotating the tree to the left.
*/
nvgpu_rbtree_unlink(more_elements[5], &root);
/* No impact on coverage */
nvgpu_rbtree_unlink(more_elements[6], &root);
nvgpu_rbtree_unlink(more_elements[7], &root);
/*
* Targets statements in the link rebuilding of the rotate_left
* function. Also targets some conditions when removing a node on the
* right and the left needs to become black.
*/
nvgpu_rbtree_unlink(more_elements[8], &root);
/*
* Targets statements in the link rebuilding of nvgpu_rbtree_unlink
*/
nvgpu_rbtree_unlink(more_elements[9], &root);
/* No impact on coverage */
nvgpu_rbtree_unlink(more_elements[10], &root);
nvgpu_rbtree_unlink(more_elements[11], &root);
nvgpu_rbtree_unlink(more_elements[12], &root);
nvgpu_rbtree_unlink(more_elements[13], &root);
nvgpu_rbtree_unlink(more_elements[14], &root);
nvgpu_rbtree_unlink(more_elements[15], &root);
nvgpu_rbtree_unlink(more_elements[16], &root);
nvgpu_rbtree_unlink(more_elements[17], &root);
/*
* Targets statements in the link rebuilding of delete_fixup (right
* sibling of deleted node is black or has a right sentinel)
*/
nvgpu_rbtree_unlink(more_elements[18], &root);
/*
* Targets statement in the rotate_left function (the rotated node
* becomes the root of the tree)
*/
nvgpu_rbtree_unlink(more_elements[19], &root);
/* No impact on coverage */
nvgpu_rbtree_unlink(more_elements[20], &root);
nvgpu_rbtree_unlink(more_elements[21], &root);
nvgpu_rbtree_unlink(more_elements[22], &root);
free_test_tree(m, root);
for (i = 0; i < num_elems; i++) {
free(more_elements[i]);
}
free(more_elements);
return UNIT_SUCCESS;
}
struct unit_module_test interface_rbtree_tests[] = {
UNIT_TEST(insert, test_insert, NULL, 0),
UNIT_TEST(search, test_search, NULL, 0),
UNIT_TEST(unlink, test_unlink, NULL, 0),
UNIT_TEST(enum, test_enum, NULL, 0),
UNIT_TEST(enum_next, test_enum_next, NULL, 0),
UNIT_TEST(search_less_than, test_search_less, NULL, 0),
UNIT_TEST(unlink_corner_cases, test_unlink_corner_cases, NULL, 0),
};
UNIT_MODULE(interface_rbtree, interface_rbtree_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,296 @@
/*
* Copyright (c) 2019, 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_RBTREE_H
#define UNIT_RBTREE_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-rbtree
* @{
*
* Software Unit Test Specification for interface.rbtree
*
* To make testing easier, most tests will use the same rbtree that is built
* according to:
* - The tree will contain 9 nodes (10 insertions, but one rejected as
* duplicate).
* - The values in the tree express a range. All nodes have the same range.
* - The values and the order in which they are inserted is carefully chosen
* to maximize code coverage by ensuring that all corner cases are hit.
*
* Refer to #initial_key_start for the definition of the test tree.
*/
/**
* Number of initial elements in the test tree.
*/
#define INITIAL_ELEMENTS 10
/**
* Range of each element in the test tree.
*/
#define RANGE_SIZE 10U
/**
* This value is to be used twice in the test tree to create a duplicate.
*/
#define DUPLICATE_VALUE 300
/**
* Sample tree used throughout this unit. Node values below are key_start.
*
* 130 (Black)
* / \
* / \
* 50 200 (Red)
* / \ / \
* 30 80 170 300 (Black)
* / /
* 10 120 (Red)
*
* NOTE: There is a duplicate entry that will be ignored during insertion.
*/
u64 initial_key_start[] = {50, 30, 80, 100, 170, 10, 200, DUPLICATE_VALUE,
DUPLICATE_VALUE, 120};
/**
* The following key value should not exist or cover a range from the keys
* above.
*/
#define INVALID_KEY_START 2000
/**
* The following key will be used to search and range_search in the tree. It is
* chosen so that paths taken will involve both left and right branches.
*/
#define SEARCH_KEY 120
/**
* The values below will cause the red-black properties to be violated upon
* insertion into the tree defined above. As a result, these will trigger
* specific cases during the tree rebalancing procedure.
*/
#define RED_BLACK_VIOLATION_1 20
#define RED_BLACK_VIOLATION_2 320
/**
* Test specification for: test_insert
*
* Description: Test to check the nvgpu_rbtree_insert operation.
*
* Test Type: Feature
*
* Targets: nvgpu_rbtree_insert
*
* Input: None
*
* Steps:
* - Create a test tree with known values.
* - Perform all the checks to ensure the resulting tree has all the properties
* of a red-black tree.
* - Insert 2 well known values defined by RED_BLACK_VIOLATION_1 and
* RED_BLACK_VIOLATION_2 to cause red-black violations upon insertion.
* - Check the red-black correctness again to ensure that the insertion
* algorithm rebalanced the tree after the 2 insertions.
* - Free the test tree.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_insert(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_unlink
*
* Description: Test to check the nvgpu_rbtree_unlink operation by removing
* every node from a test tree
*
* Test Type: Feature
*
* Targets: nvgpu_rbtree_search, nvgpu_rbtree_unlink
*
* Input: None
*
* Steps:
* - Create a test tree with known values.
* - For each of the known values used to create the tree"
* - Use nvgpu_rbtree_search to search for the node and ensure it exists in
* the tree.
* - Use nvgpu_rbtree_unlink to unlink the node.
* - Run search again to ensure the node is not in the tree anymore.
* - Free the test tree.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_unlink(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_search
*
* Description: Test to check the nvgpu_rbtree_search and
* nvgpu_rbtree_range_search routines and go over some error handling.
*
* Test Type: Feature
*
* Targets: nvgpu_rbtree_search, nvgpu_rbtree_range_search
*
* Input: None
*
* Steps:
* - Create a test tree with known values.
* - Ensure that searching with a NULL root returns NULL.
* - Ensure that range searching with a NULL root returns NULL.
* - Ensure that searching for a known value returns a valid result.
* - Perform a range search on a value that falls within a known existing range
* and ensure it returns the correct result.
* - Free the test tree.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_search(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_enum
*
* Description: Test to check the nvgpu_rbtree_enum_start routine and go over
* some error handling.
*
* Test Type: Feature
*
* Targets: nvgpu_rbtree_enum_start
*
* Input: None
*
* Steps:
* - Create a test tree with known values.
* - Ensure that enumerating with a NULL root returns NULL.
* - For each known value of the tree, start an enumeration with the value
* itself and ensure that the resulting node's key_start is the same.
* - Start an enumeration of a key that is know to not be in the tree and ensure
* that the returned value is NULL.
* - Free the test tree.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_enum(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_enum_next
*
* Description: Test to check the nvgpu_rbtree_enum_next routine and go over
* some error handling. nvgpu_rbtree_enum_next will find the next node whose
* key_start value is greater than the one in the provided node.
*
* Test Type: Feature
*
* Targets: nvgpu_rbtree_enum_next
*
* Input: None
*
* Steps:
* - Create a test tree with known values.
* - Ensure that enum_next with a NULL root returns NULL.
* - Set a node pointer to point to the root of the tree.
* - While the node pointer is not NULL, do the following:
* - Perform an enum_next operation from the node pointer. The result is
* stored in the node pointer.
* - Ensure that the node pointer's key_start is not lower than the key_start
* value of the previous node.
* - Continue until there are no more results and enum_next changes the node
* pointer to NULL.
* - Free the test tree.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_enum_next(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_search_less
*
* Description: Test to check the nvgpu_rbtree_less_than_search routine: given
* a key_start value, find a node with a lower key_start value.
*
* Test Type: Feature
*
* Targets: nvgpu_rbtree_less_than_search
*
* Input: None
*
* Steps:
* - Create a test tree with known values.
* - Considering that after creating the tree is balanced, this implies that the
* key_start value of root is somewhere in the middle of the key_start values
* of the other nodes of the tree. So root->key_start is used for the
* less_than_search operation.
* - Perform the less_than_search operation and ensure that:
* - It yields a non-NULL result.
* - The key_start value of the resulting node is lower than root->key_start.
* - Free the test tree.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_search_less(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_unlink_corner_cases
*
* Description: Test corner cases in nvgpu_rbtree_unlink (and delete_fixup) to
* increase branch and line coverage.
*
* Test Type: Feature
*
* Targets: nvgpu_rbtree_insert, nvgpu_rbtree_unlink
*
* Input: None
*
* Steps:
* - Create a test tree with known values.
* - Unlink well chosen values to create conditions where nodes are removed on
* the left and subsequently the right side needs to become red.
* - Unlink well chosen values to create conditions where nodes are removed on
* the left and the right is NULL.
* - Unlink well chosen values to create conditions where nodes are removed on
* the left and the right side is red, requiring a tree rotation to the left.
* - Unlink well chosen values to create conditions where nodes are removed on
* the right and the left side needs to become black.
* - Unlink well chosen values to create conditions where right sibling of
* deleted node is black or has a right sentinel.
* - Unlink well chosen values to create conditions where the left rotation
* will create a new root.
* - Free the test tree.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_unlink_corner_cases(struct unit_module *m, struct gk20a *g,
void *args);
/** }@ */
#endif /* UNIT_RBTREE_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = static_analysis.o
MODULE = static_analysis
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=static_analysis
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,24 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=static_analysis
NVGPU_UNIT_SRCS=static_analysis.c
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,282 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/static_analysis.h>
#include "static_analysis.h"
int test_arithmetic(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
/* U8 sub */
unit_assert(nvgpu_safe_sub_u8(1, 1) == 0, return UNIT_FAIL);
unit_assert(nvgpu_safe_sub_u8(U8_MAX, U8_MAX) == 0,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_sub_u8(0, 1));
unit_assert(err != 0, return UNIT_FAIL);
/* U32 add */
unit_assert(nvgpu_safe_add_u32(U32_MAX-1, 1) == U32_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_add_u32(U32_MAX, 0) == U32_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_add_u32(U32_MAX, 1));
unit_assert(err != 0, return UNIT_FAIL);
/* S32 add */
unit_assert(nvgpu_safe_add_s32(INT_MAX-1, 1) == INT_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_add_s32(INT_MAX, 0) == INT_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_add_s32(INT_MIN+1, -1) == INT_MIN,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_add_s32(INT_MAX, 1));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_add_s32(INT_MIN, -1));
unit_assert(err != 0, return UNIT_FAIL);
/* U32 sub */
unit_assert(nvgpu_safe_sub_u32(1, 1) == 0, return UNIT_FAIL);
unit_assert(nvgpu_safe_sub_u32(U32_MAX, U32_MAX) == 0,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_sub_u32(0, 1));
unit_assert(err != 0, return UNIT_FAIL);
/* S32 sub */
unit_assert(nvgpu_safe_sub_s32(INT_MIN+1, 1) == INT_MIN,
return UNIT_FAIL);
unit_assert(nvgpu_safe_sub_s32(INT_MAX-1, -1) == INT_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_sub_s32(INT_MIN, 1));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_sub_s32(INT_MAX, -1));
unit_assert(err != 0, return UNIT_FAIL);
/* U32 Mult */
unit_assert(nvgpu_safe_mult_u32(0, 0) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_u32(U32_MAX, 0) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_u32(U32_MAX, 1) == U32_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_mult_u32(U32_MAX, 2));
unit_assert(err != 0, return UNIT_FAIL);
/* U64 add */
unit_assert(nvgpu_safe_add_u64(U64_MAX-1, 1) == U64_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_add_u64(U64_MAX, 0) == U64_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_add_u64(U64_MAX, 1));
unit_assert(err != 0, return UNIT_FAIL);
/* S64 add */
unit_assert(nvgpu_safe_add_s64(LONG_MAX-1, 1) == LONG_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_add_s64(LONG_MAX, 0) == LONG_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_add_s64(LONG_MIN+1, -1) == LONG_MIN,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_add_s64(LONG_MAX, 1));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_add_s64(LONG_MIN, -1));
unit_assert(err != 0, return UNIT_FAIL);
/* U64 sub */
unit_assert(nvgpu_safe_sub_u64(1, 1) == 0, return UNIT_FAIL);
unit_assert(nvgpu_safe_sub_u64(U64_MAX, U64_MAX) == 0,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_sub_u64(0, 1));
unit_assert(err != 0, return UNIT_FAIL);
/* S64 sub */
unit_assert(nvgpu_safe_sub_s64(LONG_MIN+1, 1) == LONG_MIN,
return UNIT_FAIL);
unit_assert(nvgpu_safe_sub_s64(LONG_MAX-1, -1) == LONG_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_sub_s64(LONG_MIN, 1));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_sub_s64(LONG_MAX, -1));
unit_assert(err != 0, return UNIT_FAIL);
/* U64 Mult */
unit_assert(nvgpu_safe_mult_u64(0, 0) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_u64(U64_MAX, 0) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_u64(U64_MAX, 1) == U64_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_mult_u64(U64_MAX, 2));
unit_assert(err != 0, return UNIT_FAIL);
/* S64 Mult */
unit_assert(nvgpu_safe_mult_s64(LONG_MAX, 1) == LONG_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_s64(LONG_MAX, -1) == (-1 * LONG_MAX),
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_s64(-1, LONG_MAX) == (-1 * LONG_MAX),
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_s64(0, LONG_MAX) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_s64(-1, -1) == 1,
return UNIT_FAIL);
unit_assert(nvgpu_safe_mult_s64(0, -1) == 0,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_mult_s64(LONG_MAX, 2));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_mult_s64(LONG_MAX, -2));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_mult_s64(-1*LONG_MAX, 2));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_mult_s64(-1*LONG_MAX, -2));
unit_assert(err != 0, return UNIT_FAIL);
return UNIT_SUCCESS;
}
int test_cast(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
/* U64 to U32 */
unit_assert(nvgpu_safe_cast_u64_to_u32(U32_MAX) == U32_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u64_to_u32(U64(U32_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U64 to U16 */
unit_assert(nvgpu_safe_cast_u64_to_u16(U16_MAX) == U16_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u64_to_u16(U64(U16_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U64 to U8 */
unit_assert(nvgpu_safe_cast_u64_to_u8(U8_MAX) == U8_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u64_to_u8(U64(U8_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U64 to S64 */
unit_assert(nvgpu_safe_cast_u64_to_s64(LONG_MAX) == LONG_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u64_to_s64(U64(LONG_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U64 to S32 */
unit_assert(nvgpu_safe_cast_u64_to_s32(INT_MAX) == INT_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u64_to_s32(U64(INT_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* S64 to U64 */
unit_assert(nvgpu_safe_cast_s64_to_u64(LONG_MAX) == LONG_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s64_to_u64(-1));
unit_assert(err != 0, return UNIT_FAIL);
/* S64 to U32 */
unit_assert(nvgpu_safe_cast_s64_to_u32(U32_MAX) == U32_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s64_to_u32(-1));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s64_to_u32(U64(U32_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* S64 to S32 */
unit_assert(nvgpu_safe_cast_s64_to_s32(INT_MAX) == INT_MAX,
return UNIT_FAIL);
unit_assert(nvgpu_safe_cast_s64_to_s32(INT_MIN) == INT_MIN,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s64_to_s32(S64(INT_MIN)-1));
unit_assert(err != 0, return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s64_to_s32(S64(INT_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U32 to U16 */
unit_assert(nvgpu_safe_cast_u32_to_u16(U16_MAX) == U16_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u32_to_u16(U64(U16_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U32 to U8 */
unit_assert(nvgpu_safe_cast_u32_to_u8(U8_MAX) == U8_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u32_to_u8(U64(U8_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U32 to S32 */
unit_assert(nvgpu_safe_cast_u32_to_s32(INT_MAX) == INT_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u32_to_s32(U32(INT_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* U32 to S8 */
unit_assert(nvgpu_safe_cast_u32_to_s8(SCHAR_MAX) == SCHAR_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_u32_to_s8(U32(SCHAR_MAX)+1));
unit_assert(err != 0, return UNIT_FAIL);
/* S32 to U64 */
unit_assert(nvgpu_safe_cast_s32_to_u64(INT_MAX) == INT_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s32_to_u64(-1));
unit_assert(err != 0, return UNIT_FAIL);
/* S32 to U32 */
unit_assert(nvgpu_safe_cast_s32_to_u32(INT_MAX) == INT_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s32_to_u32(-1));
unit_assert(err != 0, return UNIT_FAIL);
/* S8 to U8 */
unit_assert(nvgpu_safe_cast_s8_to_u8(SCHAR_MAX) == SCHAR_MAX,
return UNIT_FAIL);
err = EXPECT_BUG((void)nvgpu_safe_cast_s8_to_u8(-1));
unit_assert(err != 0, return UNIT_FAIL);
/* bool to U32 */
unit_assert(nvgpu_safe_cast_bool_to_u32(false) == 0, return UNIT_FAIL);
unit_assert(nvgpu_safe_cast_bool_to_u32(true) == 1, return UNIT_FAIL);
return UNIT_SUCCESS;
}
int test_safety_checks(struct unit_module *m, struct gk20a *g, void *args)
{
nvgpu_safety_checks();
return UNIT_SUCCESS;
}
struct unit_module_test static_analysis_tests[] = {
UNIT_TEST(arithmetic, test_arithmetic, NULL, 0),
UNIT_TEST(cast, test_cast, NULL, 0),
UNIT_TEST(safety_checks, test_safety_checks, NULL, 0),
};
UNIT_MODULE(static_analysis, static_analysis_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_STATIC_ANALYSIS_H
#define UNIT_STATIC_ANALYSIS_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-static_analysis
* @{
*
* Software Unit Test Specification for static analysis unit
*/
/**
* Test specification for: test_arithmetic
*
* Description: Verify functionality of static analysis safe arithmetic APIs.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_safe_sub_u8, nvgpu_safe_add_u32, nvgpu_safe_add_s32,
* nvgpu_safe_sub_u32, nvgpu_safe_sub_s32, nvgpu_safe_mult_u32,
* nvgpu_safe_add_u64, nvgpu_safe_add_s64, nvgpu_safe_sub_u64,
* nvgpu_safe_sub_s64, nvgpu_safe_mult_u64, nvgpu_safe_mult_s64
*
* Input: None
*
* Steps:
* - Call the static analysis arithmetic APIs. Pass in valid values and verify
* correct return.
* - Call the static analysis arithmetic APIs. Pass in values beyond type range
* and use EXPECT_BUG() to verify BUG() is called.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_arithmetic(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_cast
*
* Description: Verify functionality of static analysis safe cast APIs.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_safe_cast_u64_to_u32, nvgpu_safe_cast_u64_to_u16,
* nvgpu_safe_cast_u64_to_u8, nvgpu_safe_cast_u64_to_s64,
* nvgpu_safe_cast_u64_to_s32, nvgpu_safe_cast_s64_to_u64,
* nvgpu_safe_cast_s64_to_u32, nvgpu_safe_cast_s64_to_s32,
* nvgpu_safe_cast_u32_to_u16, nvgpu_safe_cast_u32_to_u8,
* nvgpu_safe_cast_u32_to_s32, nvgpu_safe_cast_u32_to_s8,
* nvgpu_safe_cast_s32_to_u64, nvgpu_safe_cast_s32_to_u32,
* nvgpu_safe_cast_s8_to_u8, nvgpu_safe_cast_bool_to_u32
*
* Input: None
*
* Steps:
* - Call the static analysis arithmetic APIs. Pass in valid values and verify
* correct return.
* - Call the static analysis arithmetic APIs. Pass in values beyond type range
* and use EXPECT_BUG() to verify BUG() is called.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_cast(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_safety_checks
*
* Description: Verify functionality of static analysis safety_check() API.
*
* Test Type: Feature
*
* Targets: nvgpu_safety_checks
*
* Input: None
*
* Steps:
* - Call the API nvgpu_safety_checks(). No error should occur.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_safety_checks(struct unit_module *m, struct gk20a *g, void *args);
/**
* @}
*/
#endif /* UNIT_STATIC_ANALYSIS_H */

View File

@@ -0,0 +1,26 @@
# Copyright (c) 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = nvgpu-string.o
MODULE = nvgpu-string
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu-string
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,24 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu-string
NVGPU_UNIT_SRCS=nvgpu-string.c
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/string.h>
#include "nvgpu-string.h"
#include <string.h>
int test_memcpy_memcmp(struct unit_module *m, struct gk20a *g, void *args)
{
const size_t len = 10;
u8 dest[len];
u8 src[len];
u8 i;
for (i = 0; i < len; i++) {
dest[i] = 0;
src[i] = i;
}
nvgpu_memcpy(dest, src, len);
unit_assert(nvgpu_memcmp(dest, src, len) == 0, return UNIT_FAIL);
for (i = 0; i < len; i++) {
dest[i] = 0;
}
nvgpu_memcpy(dest, src, len - 1U);
unit_assert(nvgpu_memcmp(dest, src, len - 1U) == 0, return UNIT_FAIL);
unit_assert(dest[len - 1] == 0, return UNIT_FAIL);
unit_assert(nvgpu_memcmp(dest, src, len) != 0, return UNIT_FAIL);
/* test size==0 */
unit_assert(nvgpu_memcmp(dest, src, 0) == 0, return UNIT_FAIL);
return UNIT_SUCCESS;
}
int test_strnadd_u32(struct unit_module *m, struct gk20a *g, void *args)
{
const size_t len = 10;
char dest[len];
/* test invalid radices */
unit_assert(nvgpu_strnadd_u32(dest, 10U, len, 1U) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_strnadd_u32(dest, 10U, len, 17U) == 0,
return UNIT_FAIL);
/* test insufficient space */
unit_assert(nvgpu_strnadd_u32(dest, 1000U, 2, 10U) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_strnadd_u32(dest, 1000U, 4, 10U) == 0,
return UNIT_FAIL);
unit_assert(nvgpu_strnadd_u32(dest, 1000U, len, 10U) == 4,
return UNIT_FAIL);
unit_assert(strncmp(dest, "1000", 4) == 0, return UNIT_FAIL);
unit_assert(nvgpu_strnadd_u32(dest, 0xdeadbeef, len, 16U) == 8,
return UNIT_FAIL);
unit_assert(strncmp(dest, "deadbeef", 8) == 0, return UNIT_FAIL);
return UNIT_SUCCESS;
}
int test_mem_is_word_aligned(struct unit_module *m, struct gk20a *g, void *args)
{
unit_assert(nvgpu_mem_is_word_aligned(g, (u8 *)0x1000),
return UNIT_FAIL);
unit_assert(!nvgpu_mem_is_word_aligned(g, (u8 *)0x1001),
return UNIT_FAIL);
unit_assert(!nvgpu_mem_is_word_aligned(g, (u8 *)0x1002),
return UNIT_FAIL);
unit_assert(!nvgpu_mem_is_word_aligned(g, (u8 *)0x1003),
return UNIT_FAIL);
unit_assert(nvgpu_mem_is_word_aligned(g, (u8 *)0x1004),
return UNIT_FAIL);
return UNIT_SUCCESS;
}
struct unit_module_test string_tests[] = {
UNIT_TEST(memcpy_memcmp, test_memcpy_memcmp, NULL, 0),
UNIT_TEST(strnadd_u32, test_strnadd_u32, NULL, 0),
UNIT_TEST(mem_is_word_aligned, test_mem_is_word_aligned, NULL, 0),
};
UNIT_MODULE(string, string_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_STRING_H
#define UNIT_STRING_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-string
* @{
*
* Software Unit Test Specification for worker unit
*/
/**
* Test specification for: test_memcpy_memcmp
*
* Description: Test functionality of the utility functions nvgpu_memcpy and
* nvgpu_memcmp.
*
* Test Type: Feature, Error guessing, Boundary values
*
* Targets: nvgpu_memcpy, nvgpu_memcmp
*
* Input: None.
*
* Steps:
* - Initialize source array to the values 1-10.
* - Initialize destination array to all 0's.
* - Call nvgpu_memcpy with the source & destination arrays, passing the full
* length.
* - Call nvgpu_memcmp with the source & destination arrays, passing the full
* length. Verify it returns a match.
* - Re-init destination to 0.
* - Call nvgpu_memcpy with the source & destination arrays, passing length-1.
* - Call nvgpu_memcmp with the source & destination arrays, passing length-1.
* Verify it returns a match.
* - Verify the final element of the destination array is still 0.
* - Call nvgpu_memcmp with the source & destination arrays, passing length.
* Verify it returns a non-match.
* - Call nvgpu_memcmp with a length 0. Verify a match is returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_memcpy_memcmp(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_strnadd_u32
*
* Description: Test functionality of the utility function test_strnadd_u32.
*
* Test Type: Feature, Error guessing, Boundary values
*
* Targets: nvgpu_strnadd_u32
*
* Input: None.
*
* Steps:
* - Call nvgpu_strnadd_u32 with invalid radices. Verify 0 is returned.
* - Call nvgpu_strnadd_u32 with an insufficient string size for the requested.
* number. Verify 0 is returned.
* - Call nvgpu_strnadd_u32 with a decimal value of 1000. Verify returned size
* is 4 and the string contains "1000".
* - Call nvgpu_strnadd_u32 with a hexidecimal value of 0xdeadbeef. Verify
* returned size is 8 and the string contains "deadbeef".
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_strnadd_u32(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_mem_is_word_aligned
*
* Description: Test functionality of the utility function
* nvgpu_mem_is_word_aligned.
*
* Test Type: Feature, Error guessing, Boundary values
*
* Targets: nvgpu_mem_is_word_aligned
*
* Input: None.
*
* Steps:
* - Call nvgpu_mem_is_word_aligned with various addresses and verify the
* correct value is returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_mem_is_word_aligned(struct unit_module *m, struct gk20a *g, void *args);
/**
* @}
*/
#endif /* UNIT_STRING_H */

View File

@@ -0,0 +1,26 @@
# 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"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = worker.o
MODULE = worker
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019-2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=worker
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,24 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019-2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=worker
NVGPU_UNIT_SRCS=worker.c
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,354 @@
/*
* 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/worker.h>
#include <nvgpu/thread.h>
#include <nvgpu/timers.h>
#include <nvgpu/atomic.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include "worker.h"
/*
* nvgpu_worker_ops functions
*/
static nvgpu_atomic_t pre_process_count;
static void pre_process(struct nvgpu_worker *worker)
{
nvgpu_atomic_inc(&pre_process_count);
}
static bool force_early_exit = false;
static nvgpu_atomic_t wakeup_early_exit_count;
static bool wakeup_early_exit(struct nvgpu_worker *worker)
{
nvgpu_atomic_inc(&wakeup_early_exit_count);
if (force_early_exit) {
return true;
}
return nvgpu_worker_should_stop(worker);
}
static nvgpu_atomic_t wakeup_post_process_val;
static void wakeup_post_process(struct nvgpu_worker *worker)
{
nvgpu_atomic_inc(&wakeup_post_process_val);
}
static void wakeup_post_process_stop_thread(struct nvgpu_worker *worker)
{
struct nvgpu_posix_fault_inj *thread_fi =
nvgpu_thread_get_fault_injection();
nvgpu_posix_enable_fault_injection(thread_fi, true, 0);
nvgpu_atomic_inc(&wakeup_post_process_val);
}
static bool stall_processing = false;
static nvgpu_atomic_t item_count;
static void wakeup_process_item(struct nvgpu_list_node *work_item)
{
bool stall = stall_processing;
nvgpu_atomic_inc(&item_count);
while (stall) {
nvgpu_udelay(5);
stall = stall_processing;
}
}
static bool wakeup_condition_val = false;
static bool wakeup_condition(struct nvgpu_worker *worker)
{
return wakeup_condition_val;
}
static u32 wakeup_timeout_val = 0U;
static u32 wakeup_timeout(struct nvgpu_worker *worker)
{
return wakeup_timeout_val;
}
_Thread_local struct nvgpu_worker worker;
_Thread_local struct nvgpu_worker worker_branch;
_Thread_local struct nvgpu_worker_ops worker_ops = {
/* pre_process is NULL for branch testing for NULL when thread starts. */
.pre_process = NULL,
.wakeup_early_exit = wakeup_early_exit,
.wakeup_post_process = wakeup_post_process,
.wakeup_process_item = wakeup_process_item,
.wakeup_condition = wakeup_condition,
.wakeup_timeout = wakeup_timeout,
};
int test_init(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
struct nvgpu_posix_fault_inj *thread_fi =
nvgpu_thread_get_fault_injection();
char tmp[sizeof(worker.thread_name)+10];
memset(tmp, 'g', sizeof(tmp) - 1);
tmp[sizeof(tmp) - 1] = '\0';
/* init with a long name to get branch coverage */
nvgpu_worker_init_name(&worker, tmp,
"A long-named simulated unit test gpu");
/* init with a reasonable name */
nvgpu_worker_init_name(&worker, "testworker", "gpu");
/* enable fault injection to create error starting thread for worker */
nvgpu_posix_enable_fault_injection(thread_fi, true, 0);
err = nvgpu_worker_init(g, &worker, &worker_ops);
unit_assert(err != 0, return UNIT_FAIL);
nvgpu_posix_enable_fault_injection(thread_fi, false, 0);
/* normal init */
err = nvgpu_worker_init(g, &worker, &worker_ops);
unit_assert(err == 0, return UNIT_FAIL);
/* init when already running */
while (!nvgpu_thread_is_running(&worker.poll_task)) {
nvgpu_udelay(5);
}
nvgpu_atomic_set(&worker_branch.poll_task.running, 1);
err = nvgpu_worker_init(g, &worker_branch, &worker_ops);
unit_assert(err == 0, return UNIT_FAIL);
return UNIT_SUCCESS;
}
int test_enqueue(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
const unsigned int num_work_items = 3U;
struct nvgpu_list_node work_items[num_work_items];
unsigned int i;
for (i = 0U; i < num_work_items; i++) {
nvgpu_init_list_node(&work_items[i]);
}
nvgpu_atomic_set(&item_count, 0);
for (i = 0U; i < num_work_items; i++) {
err = nvgpu_worker_enqueue(&worker, &work_items[i]);
unit_assert(err == 0, return UNIT_FAIL);
}
/* wait until all items are processed */
while ((u32)nvgpu_atomic_read(&item_count) < num_work_items) {
nvgpu_udelay(5);
}
/*
* Test requeueing same item. To do this, we have to stall the worker
* in the processing loop so we can make sure the item isn't removed.
*/
stall_processing = true;
nvgpu_init_list_node(&work_items[0]);
err = nvgpu_worker_enqueue(&worker, &work_items[0]);
unit_assert(err == 0, return UNIT_FAIL);
while ((u32)nvgpu_atomic_read(&item_count) < (num_work_items + 1)) {
nvgpu_udelay(5);
}
err = nvgpu_worker_enqueue(&worker, &work_items[0]);
unit_assert(err == 0, return UNIT_FAIL);
err = nvgpu_worker_enqueue(&worker, &work_items[0]);
unit_assert(err != 0, return UNIT_FAIL);
stall_processing = false;
while ((u32)nvgpu_atomic_read(&item_count) < (num_work_items + 2)) {
nvgpu_udelay(5);
}
return UNIT_SUCCESS;
}
int test_branches(struct unit_module *m, struct gk20a *g, void *args)
{
int err;
struct nvgpu_list_node work_item;
int last_item_count;
struct nvgpu_posix_fault_inj *thread_fi =
nvgpu_thread_get_fault_injection();
struct nvgpu_posix_fault_inj *thread_running_fi =
nvgpu_thread_running_true_get_fault_injection();
unsigned int i;
/*
* make timeout value short to get those branches, but have to
* call enqueue to make it trigger
*/
wakeup_timeout_val = 1U;
nvgpu_atomic_set(&wakeup_post_process_val, 0);
nvgpu_init_list_node(&work_item);
err = nvgpu_worker_enqueue(&worker, &work_item);
unit_assert(err == 0, return UNIT_FAIL);
while (nvgpu_atomic_read(&wakeup_post_process_val) < 10) {
nvgpu_udelay(5);
}
wakeup_timeout_val = 0U;
/* cover branches where these ops are NULL */
worker_ops.wakeup_condition = NULL;
worker_ops.wakeup_timeout = NULL;
worker_ops.wakeup_early_exit = NULL;
worker_ops.wakeup_post_process = NULL;
/* do this twice to make sure each is given a chance */
for (i = 0U; i < 2; i++) {
last_item_count = nvgpu_atomic_read(&item_count);
err = nvgpu_worker_enqueue(&worker, &work_item);
unit_assert(err == 0, return UNIT_FAIL);
while (last_item_count == nvgpu_atomic_read(&item_count)) {
nvgpu_udelay(5);
}
}
worker_ops.wakeup_condition = wakeup_condition;
worker_ops.wakeup_timeout = wakeup_timeout;
worker_ops.wakeup_early_exit = wakeup_early_exit;
worker_ops.wakeup_post_process = wakeup_post_process;
/* cover branch for the wakeup_condition op */
nvgpu_atomic_set(&wakeup_post_process_val, 0);
wakeup_condition_val = true;
last_item_count = nvgpu_atomic_read(&item_count);
err = nvgpu_worker_enqueue(&worker, &work_item);
unit_assert(err == 0, return UNIT_FAIL);
while (nvgpu_atomic_read(&wakeup_post_process_val) < 1) {
nvgpu_udelay(5);
}
wakeup_condition_val = false;
/*
* Cover branches for failsafe checks for empty work. This shouldn't
* really happen, but there's logic to catch them just in case. So, we
* can't make it happen directly, so we send the cond directly.
*/
nvgpu_atomic_set(&wakeup_post_process_val, 0);
nvgpu_atomic_inc(&worker.put);
nvgpu_cond_signal_interruptible(&worker.wq);
while (nvgpu_atomic_read(&wakeup_post_process_val) < 1) {
nvgpu_udelay(5);
}
/* Cover branch for early exit. This will exit the thread. */
nvgpu_atomic_set(&wakeup_early_exit_count, 0);
force_early_exit = true;
nvgpu_init_list_node(&work_item);
err = nvgpu_worker_enqueue(&worker, &work_item);
unit_assert(err == 0, return UNIT_FAIL);
while (nvgpu_atomic_read(&wakeup_early_exit_count) < 1) {
nvgpu_udelay(5);
}
force_early_exit = false;
/* when the thread exists, we need sync some state */
nvgpu_thread_stop(&worker.poll_task);
/*
* While the thread is stopped, we can hit a branch in enqueue where
* starting the thread fails.
*/
nvgpu_init_list_node(&work_item);
nvgpu_posix_enable_fault_injection(thread_fi, true, 0);
if (!EXPECT_BUG(nvgpu_worker_enqueue(&worker, &work_item))) {
unit_return_fail(m, "should have failed to enqueue\n");
}
nvgpu_posix_enable_fault_injection(thread_fi, false, 0);
/*
* While the thread is stopped, we can hit a branch in the worker start
* function where the first check for thread running is false, then
* second check is true.
*/
nvgpu_init_list_node(&work_item);
nvgpu_posix_enable_fault_injection(thread_running_fi, true, 1);
err = nvgpu_worker_enqueue(&worker, &work_item);
unit_assert(err == 0, return UNIT_FAIL);
nvgpu_posix_enable_fault_injection(thread_running_fi, false, 0);
/* Re-init the worker to start the thread for next test. */
worker_ops.pre_process = pre_process;
nvgpu_atomic_set(&pre_process_count, 0);
nvgpu_worker_init(g, &worker, &worker_ops);
unit_assert(err == 0, return UNIT_FAIL);
/* make sure thread has started */
while (nvgpu_atomic_read(&pre_process_count) < 1) {
nvgpu_udelay(5);
}
/*
* Test for loop checking for thread_should_stop. The
* wakeup_post_process callback will enable the thread fault inject
* so nvgpu_thread_should_stop will return true.
* This will exit the thread.
*/
worker_ops.wakeup_post_process = wakeup_post_process_stop_thread;
nvgpu_atomic_set(&wakeup_post_process_val, 0);
nvgpu_init_list_node(&work_item);
err = nvgpu_worker_enqueue(&worker, &work_item);
unit_assert(err == 0, return UNIT_FAIL);
while (nvgpu_atomic_read(&wakeup_post_process_val) < 1) {
nvgpu_udelay(5);
}
/* there's no way to know the thread has exited, so wait a little */
nvgpu_udelay(1000);
worker_ops.wakeup_post_process = wakeup_post_process;
nvgpu_posix_enable_fault_injection(thread_fi, false, 0);
/* when the thread exists, we need sync some state */
nvgpu_thread_stop(&worker.poll_task);
/* Re-init the worker to start the thread for de-init testing. */
worker_ops.pre_process = pre_process;
nvgpu_atomic_set(&pre_process_count, 0);
nvgpu_worker_init(g, &worker, &worker_ops);
unit_assert(err == 0, return UNIT_FAIL);
/* make sure thread has started */
while (nvgpu_atomic_read(&pre_process_count) < 1) {
nvgpu_udelay(5);
}
return UNIT_SUCCESS;
}
int test_deinit(struct unit_module *m, struct gk20a *g, void *args)
{
nvgpu_worker_deinit(&worker);
nvgpu_udelay(10);
return UNIT_SUCCESS;
}
struct unit_module_test worker_tests[] = {
UNIT_TEST(init, test_init, NULL, 0),
UNIT_TEST(enqueue, test_enqueue, NULL, 1),
UNIT_TEST(branches, test_branches, NULL, 0),
UNIT_TEST(deinit, test_deinit, NULL, 0),
};
UNIT_MODULE(worker, worker_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,175 @@
/*
* 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_WORKER_H
#define UNIT_WORKER_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-interface-worker
* @{
*
* Software Unit Test Specification for worker unit
*/
/**
* Test specification for: test_init
*
* Description: Verify functionality of worker init APIs.
*
* Test Type: Feature, Error guessing, Boundary values
*
* Targets: nvgpu_worker_init_name, nvgpu_worker_init
*
* Input: None
*
* Steps:
* - Case 1:
* - Call nvgpu_worker_init_name() with a long name to verify the API can
* handle strings longer than the worker struct supports.
* - Case 2:
* - Call nvgpu_worker_init_name() with a short name to get full line/branch
* coverage.
* - Case 3:
* - Enable fault injection for creating threads.
* - Call nvgpu_worker_init() and verify it returns an error.
* - Disable fault injection for creating threads.
* - Case 4:
* - Call nvgpu_worker_init() and verify it returns success.
* - Case 5:
* - Call nvgpu_worker_init() and verify it returns success to verify the API
* can handle being called after the worker is already initialized.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_init(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_enqueue
*
* Description: Verify functionality of worker enqueue API.
*
* Test Type: Feature, Error guessing
*
* Targets: nvgpu_worker_enqueue
*
* Input: test_init shall have run.
*
* Steps:
* - Initialize work items.
* - Case 1:
* - Enqueue work items, verify success.
* - Wait until all work items have been processed.
* - Case 2:
* - Enqueue a work item.
* - Before the item is processed, enqueue it again and verify error is
* returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_enqueue(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_branches
*
* Description: Test a variety of special cases and error checking in the
* worker enqueue API and worker thread.
*
* Test Type: Feature, Error injection, Error guessing
*
* Targets: nvgpu_worker_enqueue, nvgpu_worker_should_stop
*
* Input: test_init shall have run.
*
* Steps:
* - Case 1: Coverage for wait timeout.
* - Make timeout value for thread very short.
* - Enqueue a work item to trigger thread to break out of waiting state.
* - Wait until thread has executed processing at least 10 times.
* - Reset timeout value to maximum.
* - Case 2: Coverage for worker_ops being NULL.
* - Set worker_op function pointers to NULL to verify these conditions
* are correctly handled by the worker thread.
* - Enqueue 3 work items to ensure all the conditions are checked in the
* thread loop.
* - Restore original worker_ops.
* - Case 3: Coverage for wakeup_condition op returning true;
* - Setup wakeup_condition worker op to return true.
* - Enqueue a work item.
* - Wait until the the item has been processed.
* - Case 4: Coverage for unexpected empty work item list.
* - Increment the worker put value to appear there is work pending.
* - Wake the thread by signalling the condition.
* - Wait for the thread to iterate the loop.
* - Case 5: Coverage for the wakeup_early_exit op returning true.
* - Setup the wakeup_early_exit op to return true.
* - Enqueue a work item.
* - Wait for the thread to detect the early exit condition.
* - NOTE: This causes the worker thread to exit.
* - Case 6: Coverage for failure to start thread.
* - Enable fault injection for creating threads.
* - Enqueue a work item (which will try to restart the thread).
* - Verify error is returned.
* - Disable fault injection for creating threads.
* - Case 7: Coverage for starting a thread and state changes.
* - Enable fault injection for checking if thread is running to return true
* on second call.
* - Enqueue a work item (which will try to restart the thread).
* - Verify no error is returned.
* - Disable fault injection for checking if thread is running.
* - Re-init the worker to restart the thread properly for next test.
* - Case 8: Test thread stopping when thread_should_stop is set.
* - Enqueue a work item.
* - In, the wakeup_post_process callback, set the thread fault injection.
* - Wait until thread exits.
* - Disable thread fault injection.
* - Re-init the worker to restart the thread properly for next test.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_branches(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_deinit
*
* Description: Test functionality of the deinit API.
*
* Test Type: Feature
*
* Targets: nvgpu_worker_deinit
*
* Input: test_init shall have run.
*
* Steps:
* - Call the nvgpu_worker_deinit() API.
* - Wait 10us to ensure it has time to stop the running thread.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_deinit(struct unit_module *m, struct gk20a *g, void *args);
/**
* @}
*/
#endif /* UNIT_WORKER_H */