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) 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 = posix-bitops.o
MODULE = posix-bitops
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=posix-bitops
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=posix-bitops
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,743 @@
/*
* Copyright (c) 2018-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/bitops.h>
#include "posix-bitops.h"
#define NUM_WORDS 4
static unsigned long single_ulong_maps[] = {
0UL,
~0UL,
0xff00ff00UL,
0x00ff00ffUL,
0xa5a5a5a5UL,
0x0000ffffUL,
0xffff0000UL,
0x1UL,
0x80000000UL,
BIT(16),
};
/*
* Can't fail - just some info prints.
*/
int test_bitmap_info(struct unit_module *m, struct gk20a *g, void *args)
{
unit_info(m, "sizeof(unsigned long) = %zu\n", sizeof(unsigned long));
unit_info(m, "BITS_PER_LONG = %lu\n", BITS_PER_LONG);
return UNIT_SUCCESS;
}
int test_ffs(struct unit_module *m, struct gk20a *g, void *args)
{
#define CHECK_FFS_WORD(w, answer) \
do { \
unsigned long ret = nvgpu_ffs(w); \
\
if (ret != (answer)) \
unit_return_fail(m, \
"ffs(0x%016lx) = %lu " \
"[expected %lu]\n", \
w, ret, answer); \
} while (0)
unsigned long i;
CHECK_FFS_WORD(single_ulong_maps[0], 0UL);
CHECK_FFS_WORD(single_ulong_maps[1], 1UL);
CHECK_FFS_WORD(single_ulong_maps[2], 9UL);
CHECK_FFS_WORD(single_ulong_maps[3], 1UL);
CHECK_FFS_WORD(single_ulong_maps[4], 1UL);
CHECK_FFS_WORD(single_ulong_maps[5], 1UL);
CHECK_FFS_WORD(single_ulong_maps[6], 17UL);
CHECK_FFS_WORD(single_ulong_maps[7], 1UL);
CHECK_FFS_WORD(single_ulong_maps[8], 32UL);
CHECK_FFS_WORD(single_ulong_maps[9], 17UL);
#undef CHECK_FFS_WORD
/*
* Also just test every bit to make sure we definitely cover all
* possible return values of the function.
*/
for (i = 0; i < BITS_PER_LONG; i++) {
if (nvgpu_ffs(BIT(i)) != (i + 1))
unit_return_fail(m, "ffs(1 << %lu) != %lu [%lu]!\n",
i, i, nvgpu_ffs(BIT(i)));
}
return UNIT_SUCCESS;
}
int test_fls(struct unit_module *m, struct gk20a *g, void *args)
{
#define CHECK_FLS_WORD(w, answer) \
do { \
unsigned long ret = nvgpu_fls(w); \
\
if (ret != (answer)) \
unit_return_fail(m, \
"fls(0x%016lx) = %lu " \
"[expected = %lu]\n", \
w, ret, answer); \
} while (0)
unsigned long i;
CHECK_FLS_WORD(single_ulong_maps[0], 0UL);
CHECK_FLS_WORD(single_ulong_maps[1], BITS_PER_LONG);
CHECK_FLS_WORD(single_ulong_maps[2], 32UL);
CHECK_FLS_WORD(single_ulong_maps[3], 24UL);
CHECK_FLS_WORD(single_ulong_maps[4], 32UL);
CHECK_FLS_WORD(single_ulong_maps[5], 16UL);
CHECK_FLS_WORD(single_ulong_maps[6], 32UL);
CHECK_FLS_WORD(single_ulong_maps[7], 1UL);
CHECK_FLS_WORD(single_ulong_maps[8], 32UL);
CHECK_FLS_WORD(single_ulong_maps[9], 17UL);
#undef CHECK_FLS_WORD
for (i = 0; i < BITS_PER_LONG; i++) {
if (nvgpu_fls(BIT(i)) != (i+1))
unit_return_fail(m, "fls(1 << %lu) != %lu! [%lu]\n",
i, i, nvgpu_fls(BIT(i)));
}
return UNIT_SUCCESS;
}
int test_ffz(struct unit_module *m, struct gk20a *g, void *args)
{
unsigned long i;
/*
* Since ffz(w) is implemented as ffs(~w) this does less extensive
* testing; but it should still cover every line of ffs().
*/
for (i = 0; i < BITS_PER_LONG; i++) {
if (ffz(~BIT(i)) != i)
unit_return_fail(m, "ffz(~(1 << %lu)) != %lu! [%lu]\n",
i, i, ffz(BIT(i)));
}
return UNIT_SUCCESS;
}
struct test_find_bit_args {
bool find_zeros;
};
static struct test_find_bit_args first_bit_args = {
.find_zeros = false
};
static struct test_find_bit_args first_zero_args = {
.find_zeros = true
};
int test_find_first_bit(struct unit_module *m, struct gk20a *g, void *__args)
{
struct test_find_bit_args *args = __args;
unsigned long words[NUM_WORDS];
unsigned long word_idx, bit_idx;
unsigned long (*finder_function)(const unsigned long *, unsigned long);
unsigned long result;
if (args->find_zeros)
finder_function = find_first_zero_bit;
else
finder_function = find_first_bit;
/*
* First test: verify that the size parameter works. We only need the
* first word for this.
*/
words[0] = ~0xffffUL;
if (args->find_zeros)
words[0] = 0xffff;
if (finder_function(words, 8UL) != 8UL)
unit_return_fail(m,
"find_first_%s(0x%lx, 8) -> %lu [WRONG]\n",
args->find_zeros ? "zero_bit" : "bit",
words[0], finder_function(words, 8UL));
if (finder_function(words, 20UL) != 16UL)
unit_return_fail(m,
"find_first_%s(0x%lx, 16) -> %lu [WRONG]\n",
args->find_zeros ? "zero_bit" : "bit",
words[0], finder_function(words, 20UL));
/*
* Now make sure that for full/empty bitmap find_next_*() returns
* the size parameter.
*/
memset(words, args->find_zeros ? 0xff : 0x00,
NUM_WORDS * sizeof(words[0]));
result = finder_function(words, NUM_WORDS * BITS_PER_LONG);
if (result != NUM_WORDS * BITS_PER_LONG)
unit_return_fail(m, "find_first_%s() failed with empty map\n",
args->find_zeros ? "zero_bit" : "bit");
/*
* Third test: set (or zero) the entire bitmap and incrementally clear
* bits. Check that we are correct even with multiple words.
*/
memset(words, args->find_zeros ? 0x00 : 0xff, sizeof(words));
for (word_idx = 0; word_idx < NUM_WORDS; word_idx++) {
for (bit_idx = 0; bit_idx < BITS_PER_LONG; bit_idx++) {
unsigned long check =
(word_idx * BITS_PER_LONG) + bit_idx;
unsigned long answer =
finder_function(words,
NUM_WORDS * BITS_PER_LONG);
if (answer != check)
unit_return_fail(m,
"find_first_%s loop: "
"word_idx = %lu bit_idx = %lu "
"-> %lu [WRONG]\n",
args->find_zeros ? "zero_bit" : "bit",
word_idx, bit_idx, answer);
/*
* Now set/clear this bit in preparation for the next
* test.
*/
if (args->find_zeros)
words[word_idx] |= BIT(bit_idx);
else
words[word_idx] &= ~BIT(bit_idx);
}
}
return UNIT_SUCCESS;
}
/*
* Note: the find_first_bit() test also effectively tests the underlying
* find_next_bit() code since find_first_bit() is just find_next_bit()
* with a 0 start.
*/
int test_find_next_bit(struct unit_module *m, struct gk20a *g, void *__args)
{
unsigned long words[NUM_WORDS];
unsigned long i, result;
/*
* Fully unset list. Should always return size.
*/
memset(words, 0x00, sizeof(words));
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) {
result = find_next_bit(words, NUM_WORDS * BITS_PER_LONG, i);
if (result != NUM_WORDS * BITS_PER_LONG)
unit_return_fail(m, "Fail: empty map (%lu)\n", i);
}
/*
* Use a fully set list but increment the offset.
*/
memset(words, 0xff, sizeof(words));
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) {
unsigned long first =
find_next_bit(words, NUM_WORDS * BITS_PER_LONG, i);
if (first != i)
unit_return_fail(m,
"Fail: first = %lu; should be %lu\n",
first, i);
}
/*
* Start > n should return n.
*/
#define TEST_START_GREATER_THAN_N(m, map, n, start) \
do { \
if (find_next_bit(map, n, start) != n) \
unit_return_fail(m, \
"Start not greater than N ?? " \
"start=%lu, N=%lu\n", \
start, n); \
} while (0)
TEST_START_GREATER_THAN_N(m, words, BITS_PER_LONG, BITS_PER_LONG + 1);
TEST_START_GREATER_THAN_N(m, words, 32UL, 64UL);
TEST_START_GREATER_THAN_N(m, words,
BITS_PER_LONG * 2, (BITS_PER_LONG * 2) + 1);
TEST_START_GREATER_THAN_N(m, words, 0UL, 1UL);
TEST_START_GREATER_THAN_N(m, words, 0UL, BITS_PER_LONG * 2);
TEST_START_GREATER_THAN_N(m, words, 0UL, BITS_PER_LONG * NUM_WORDS + 1);
#undef TEST_START_GREATER_THAN_N
return UNIT_SUCCESS;
}
#define TEST_BITMAP_SIZE (BITS_PER_LONG * 4)
/*
* 32/64 bit invarient.
*/
static DECLARE_BITMAP(bmap_all_zeros, TEST_BITMAP_SIZE) =
{
0x0UL, 0x0UL, 0x0UL, 0x0UL
};
static DECLARE_BITMAP(bmap_all_ones, TEST_BITMAP_SIZE) =
{
~0x0UL, ~0x0UL, ~0x0UL, ~0x0UL
};
int test_find_zero_area(struct unit_module *m, struct gk20a *g, void *unused)
{
#define FAIL_MSG "Fail: bmap-test='%s' (i=%lu)\n"
#define FAIL_MSG_EX "Fail: bmap-test='%s' (i=%lu, j=%lu)\n"
unsigned long i, j, result;
unsigned long words[NUM_WORDS];
for (i = 0; i < TEST_BITMAP_SIZE; i++) {
result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE, i,
TEST_BITMAP_SIZE - i, 0);
if (result != i)
unit_return_fail(m, FAIL_MSG,
"bmap_zeros: alloc-to-end", i);
result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE,
i, 1, 0);
if (result != i)
unit_return_fail(m, FAIL_MSG,
"bmap_zeros: alloc-one-bit", i);
result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE, 0,
TEST_BITMAP_SIZE - i, 0);
if (result != 0)
unit_return_fail(m, FAIL_MSG,
"bmap_zeros: alloc-i-bits-at-0", i);
}
for (i = 0; i < TEST_BITMAP_SIZE; i++) {
result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE,
i,
TEST_BITMAP_SIZE - i,
0);
if (result != i)
unit_return_fail(m, FAIL_MSG,
"all_zeros: alloc-to-end", i);
result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE,
i,
1,
0);
if (result != i)
unit_return_fail(m, FAIL_MSG,
"all_zeros: alloc-one-bit", i);
result = bitmap_find_next_zero_area(bmap_all_zeros,
TEST_BITMAP_SIZE,
0,
TEST_BITMAP_SIZE - i,
0);
if (result != 0)
unit_return_fail(m, FAIL_MSG,
"all_zeros: alloc-i-bits-at-0", i);
}
/*
* For the all ones bit map not a single alloc should succeed. We can
* just iterate through them all and make sure they all fail.
*/
for (i = 0; i < TEST_BITMAP_SIZE; i++) {
for (j = 0; j < (TEST_BITMAP_SIZE - i); j++) {
result = bitmap_find_next_zero_area(bmap_all_ones,
TEST_BITMAP_SIZE,
i,
j,
0);
if (result != TEST_BITMAP_SIZE)
unit_return_fail(m, FAIL_MSG_EX,
"all_ones: failed", i, j);
}
}
/*
* Alternating nibbles (4 bits). Make sure we don't start searching from
* too high in the bitmap since that will cause failures that are
* actually valid. This keeps the logic in the below loop a little more
* simple.
*/
memset(words, 0x0f, sizeof(words));
for (i = 0; i < ((NUM_WORDS * BITS_PER_LONG) - 8); i++) {
for (j = 0; j < ((NUM_WORDS * BITS_PER_LONG) - i - 8); j++) {
result = bitmap_find_next_zero_area(words,
NUM_WORDS * BITS_PER_LONG,
i,
j,
0);
/*
* Should only return a valid result when j < 4 (since
* the map consists of 4 ones, then 4 zeros,
* alternating.
*/
if (j <= 4 && result >= (NUM_WORDS * BITS_PER_LONG))
unit_return_fail(m, FAIL_MSG_EX,
"alternating-nibbles: failed",
i, j);
if (j > 4 && result != (NUM_WORDS * BITS_PER_LONG))
unit_return_fail(m, FAIL_MSG_EX,
"alternating-nibbles: failed",
i, j);
result = bitmap_find_next_zero_area(words,
NUM_WORDS * BITS_PER_LONG,
i,
(j % 4) + 1,
0x3);
if (result % 8 != 4)
unit_return_fail(m, FAIL_MSG_EX,
"basic-align_mask: failed",
i, j);
}
}
#undef FAIL_MSG
#undef FAIL_MSG_EX
return UNIT_SUCCESS;
}
struct test_setclear_args {
bool clear;
};
static struct test_setclear_args set_args = {
.clear = false,
};
static struct test_setclear_args clear_args = {
.clear = true,
};
static void __print_bitmap(unsigned long *map, unsigned long length)
{
unsigned int idx, bidx;
for (idx = 0; idx < (length / BITS_PER_LONG); idx++) {
printf(" ");
for (bidx = 0; bidx < BITS_PER_LONG; bidx++) {
printf("%c", (map[idx] & BIT(bidx)) ? '1' : '0');
if (bidx % 4 == 3)
printf(" ");
}
printf("\n");
}
printf("\n");
}
/*
* Verify the bits from i to i + len are set and no others are set. 'size' is in
* bits (not words).
*/
static bool verify_set_buf(unsigned long *words, unsigned long size,
unsigned long i, unsigned long len,
bool invert)
{
unsigned int idx, bidx;
unsigned int bit, bit_value;
unsigned int set_start, set_end;
unsigned int set_value = invert ? 0 : 1;
unsigned int clear_value = invert ? 1 : 0;
set_start = i;
set_end = i + len;
for (idx = 0; idx < (size / BITS_PER_LONG); idx++) {
for (bidx = 0; bidx < BITS_PER_LONG; bidx++) {
bit = idx * BITS_PER_LONG + bidx;
bit_value = !!(words[idx] & BIT(bidx));
/*
* Bit inside set zone.
*/
if ((bit >= set_start && bit < set_end) &&
bit_value != set_value)
return false;
/*
* Bit outside set zone.
*/
if ((bit < set_start || bit >= set_end) &&
bit_value != clear_value)
return false;
}
}
return true;
}
int test_single_bitops(struct unit_module *m, struct gk20a *g, void *__args)
{
unsigned long words[NUM_WORDS];
unsigned int i;
/*
* First set all the bits and make sure the words are set.
*/
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++)
nvgpu_set_bit(i, words);
if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG,
0, NUM_WORDS * BITS_PER_LONG, false)) {
__print_bitmap(words, NUM_WORDS * BITS_PER_LONG);
unit_return_fail(m, "set_bit: Failed to set a bit!\n");
}
/*
* Now make sure the test_bit works for set bits.
*/
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++)
if (!nvgpu_test_bit(i, words))
unit_return_fail(m, "test_bit: bit %d failed!\n", i);
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++)
nvgpu_clear_bit(i, words);
if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG,
0, NUM_WORDS * BITS_PER_LONG, true)) {
__print_bitmap(words, NUM_WORDS * BITS_PER_LONG);
unit_return_fail(m, "clear_bit: Failed to set a bit!\n");
}
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++)
if (nvgpu_test_bit(i, words))
unit_return_fail(m, "test_bit: bit %d failed!\n", i);
return UNIT_SUCCESS;
}
int test_bit_setclear(struct unit_module *m, struct gk20a *g, void *__args)
{
struct test_setclear_args *args = __args;
void (*testfn)(unsigned int, volatile unsigned long *) =
args->clear ? nvgpu_clear_bit : nvgpu_set_bit;
unsigned long words[NUM_WORDS];
unsigned int i;
memset(words, args->clear ? 0xff : 0x0, sizeof(words));
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++)
testfn(i, words);
if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG,
0, NUM_WORDS * BITS_PER_LONG, args->clear)) {
__print_bitmap(words, NUM_WORDS * BITS_PER_LONG);
unit_return_fail(m, "%s_bit: Failed to %s a bit!\n",
args->clear ? "clear" : "set",
args->clear ? "clear" : "set");
}
return UNIT_SUCCESS;
}
int test_test_and_setclear_bit(struct unit_module *m, struct gk20a *g,
void *__args)
{
struct test_setclear_args *args = __args;
bool (*testfn)(unsigned int, volatile unsigned long *) =
args->clear ? nvgpu_test_and_clear_bit : nvgpu_test_and_set_bit;
bool (*testfn_reset)(unsigned int, volatile unsigned long *) =
args->clear ? nvgpu_test_and_set_bit : nvgpu_test_and_clear_bit;
unsigned long words[NUM_WORDS];
unsigned int i;
memset(words, args->clear ? 0xff : 0x0, sizeof(words));
/*
* First we will set/clear the bits. Then we will clear/set the bits
* (i.e do the opposite of this loop).
*/
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) {
bool status = testfn(i, words);
if (status != args->clear) {
__print_bitmap(words, NUM_WORDS * BITS_PER_LONG);
unit_return_fail(m, "test_and_%s_bit: Failed at %d\n",
args->clear ? "clear" : "set", i);
}
}
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) {
bool status = testfn_reset(i, words);
if (status == args->clear) {
__print_bitmap(words, NUM_WORDS * BITS_PER_LONG);
unit_return_fail(m, "test_and_%s_bit: Failed at %d\n",
args->clear ? "set" : "clear", i);
}
}
/* The bitmap should be the same as we started with. */
if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG,
0, NUM_WORDS * BITS_PER_LONG, !args->clear)) {
__print_bitmap(words, NUM_WORDS * BITS_PER_LONG);
unit_return_fail(m,
"test_and_%s_bit: Final bitmap is wrong!\n",
args->clear ? "set" : "clear");
}
return UNIT_SUCCESS;
}
int test_bitmap_setclear(struct unit_module *m, struct gk20a *g, void *__args)
{
struct test_setclear_args *args = __args;
void (*testfn)(unsigned long *, unsigned int, unsigned int) =
args->clear ? nvgpu_bitmap_clear : nvgpu_bitmap_set;
unsigned long words[NUM_WORDS];
unsigned long i, j;
int set_char = args->clear ? 0xff : 0x0;
/*
* Run through all combos of set/clear for a 4 word bitmap.
*/
for (i = 0; i < NUM_WORDS * BITS_PER_LONG; i++) {
for (j = 0; j < (NUM_WORDS * BITS_PER_LONG) - i; j++) {
/*
* Just make sure we start in a known state.
*/
memset(words, set_char, sizeof(words));
testfn(words, i, j);
if (!verify_set_buf(words, NUM_WORDS * BITS_PER_LONG,
i, j, args->clear)) {
__print_bitmap(words, NUM_WORDS * BITS_PER_LONG);
unit_return_fail(m,
"%s: fail at i,j = %lu,%lu\n",
args->clear ? "clear" : "set",
i, j);
}
}
}
return UNIT_SUCCESS;
}
int test_bitops_misc(struct unit_module *m, struct gk20a *g, void *__args)
{
uint32_t i, idx, bits, numlong;
uint32_t lo, hi, mask, result;
uint64_t bitset;
bits = BITS_PER_LONG - (BITS_PER_LONG/2);
for (i = 0; i <= (BITS_PER_LONG/2); i++) {
numlong = BITS_TO_LONGS(bits);
if (numlong != (BITS_PER_LONG/BITS_PER_LONG)) {
unit_return_fail(m,
"BITS_TO_LONGS Failure %d\n", numlong);
}
bits++;
}
bits = BITS_PER_LONG + (BITS_PER_LONG/2);
for (i = 0; i <= (BITS_PER_LONG/2); i++) {
numlong = BITS_TO_LONGS(bits);
if (numlong != ((BITS_PER_LONG/BITS_PER_LONG) +1U)) {
unit_return_fail(m,
"BITS_TO_LONGS Failure %d\n", numlong);
}
bits++;
}
lo = 0;
hi = 3;
for (i = 0; i < 8; i++) {
mask = GENMASK(hi, lo);
if (((mask >> lo) & 0xf) != 0xf) {
unit_return_fail(m,
"GENMASK mask failure %x\n", mask);
}
if (~((uint32_t) (0xf << lo)) & mask) {
unit_return_fail(m,
"GENMASK extra bits Failure %x\n", mask);
}
lo += 2;
hi += 2;
}
bitset = 0xabababab;
result = 0;
for_each_set_bit(idx, &bitset, 32U) {
result |= (uint32_t)(1U << idx);
}
if (result != bitset) {
unit_return_fail(m, "for_each_set_bit Failure %x\n", result);
}
for (i = 0; i < BITS_PER_LONG; i++) {
bitset = (uint64_t)1 << (uint64_t)i;
if (bitset != BIT(i)) {
unit_return_fail(m,
"BIT Failure %d\n", mask);
}
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_bitops_tests[] = {
UNIT_TEST(info, test_bitmap_info, NULL, 0),
UNIT_TEST(ffs, test_ffs, NULL, 0),
UNIT_TEST(fls, test_fls, NULL, 0),
UNIT_TEST(ffz, test_ffz, NULL, 0),
UNIT_TEST(find_first_bit, test_find_first_bit, &first_bit_args, 0),
UNIT_TEST(find_first_zero_bit, test_find_first_bit, &first_zero_args, 0),
UNIT_TEST(find_next_bit, test_find_next_bit, NULL, 0),
UNIT_TEST(find_zero_area, test_find_zero_area, NULL, 0),
UNIT_TEST(single_bitops, test_single_bitops, NULL, 0),
UNIT_TEST(bit_set, test_bit_setclear, &set_args, 0),
UNIT_TEST(bit_clear, test_bit_setclear, &clear_args, 0),
UNIT_TEST(test_and_set_bit, test_test_and_setclear_bit, &set_args, 0),
UNIT_TEST(test_and_clear_bit, test_test_and_setclear_bit, &clear_args, 0),
UNIT_TEST(bitmap_set, test_bitmap_setclear, &set_args, 0),
UNIT_TEST(bitmap_clear, test_bitmap_setclear, &clear_args, 0),
UNIT_TEST(bitops_misc, test_bitops_misc, NULL, 0),
};
UNIT_MODULE(posix_bitops, posix_bitops_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,432 @@
/*
* 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_POSIX_BITOPS_H
#define UNIT_POSIX_BITOPS_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-posix-bitops
* @{
*
* Software Unit Test Specification for posix-bitops
*/
/**
* Test specification for: test_bitmap_info
*
* Description: Print informational log information.
*
* Test Type: Other - informational
*
* Targets: None
*
* Input: None
*
* Steps:
* - Print the number of bytes to store an "unsigned long."
* - Print the number of bits to store an "unsigned long."
*
* Output: Returns SUCCESS always
*/
int test_bitmap_info(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_ffs
*
* Description: Test the API nvgpu_ffs() (Find First Set [bit]).
*
* Test Type: Feature, Boundary values
*
* Targets: nvgpu_ffs, nvgpu_posix_ffs
*
* Input: None
*
* Steps:
* - Test passing set of pre-determined table values to nvgpu_ffs() and validate
* expected value (from table) is returned.
* - Test each bit in an "unsigned long" individually:
* - Loop through each bit in a "unsigned long."
* - Pass the constructed "unsigned long" to nvgpu_ffs().
* - Verify the correct bit is returned.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_ffs(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_fls
*
* Description: Test the API nvgpu_fls() (Find Last Set [bit]).
*
* Test Type: Feature, Boundary values
*
* Targets: nvgpu_fls, nvgpu_posix_fls
*
* Input: None
*
* Steps:
* - Test passing set of pre-determined table values to nvgpu_fls() and validate
* expected value (from table) is returned.
* - Test each bit in an "unsigned long" individually:
* - Loop through each bit in a "unsigned long."
* - Pass the constructed "unsigned long" to nvgpu_fls().
* - Verify the correct bit is returned.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_fls(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_ffz
*
* Description: Test the API ffz() (Find First Zero [bit]).
*
* Test Type: Feature, Boundary values
*
* Targets: ffz
*
* Input: None
*
* Steps:
* - Test each bit in an "unsigned long" individually:
* - Loop through each bit in a "unsigned long."
* - Pass the constructed "unsigned long" to ffz().
* - Verify the correct bit is returned.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_ffz(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_find_first_bit
*
* Description: Test the APIs find_first_zero_bit() and find_first_bit().
*
* Test Type: Feature, Boundary values
*
* Targets: find_first_zero_bit, find_first_bit
*
* Input: Pointer to struct test_find_bit_args as function parameter.
* - The parameter test_find_bit_args is used to select between testing of:
* - find_first_zero_bit()
* - find_first_bit()
*
* Steps:
* - Test the API honors the size parameter.
* - Call API with 16 bits set/zeroed and a size of 8. Verify returns 8.
* - Call API with 16 bits set/zeroed and a size of 20. Verify returns 16.
* - Call API with no bits set/zeroed and a size of 256. Verify returns 256.
* - Test each bit in an array individually:
* - Set/zero all bits in entire array.
* - Loop through incrementally setting/zeroing bits in the array.
* - Pass the constructed array to API with size of entire array (in bits).
* - Verify the correct bit is returned.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_find_first_bit(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_find_next_bit
*
* Description: Test the API find_next_bit().
*
* Test Type: Feature, Boundary values
*
* Targets: find_next_bit
*
* Input: None.
*
* Steps:
* - Test the API honors the size and start parameters.
* - Clear array of "unsigned long."
* - Loop through each bit of array:
* - Call find_next_bit() with array, size of array, and starting bit as
* the loop index.
* - Verify array size is returned (since no bit is set).
* - Set all bits in array of "unsigned long."
* - Loop through each bit of array:
* - Call find_next_bit() with array, size of array, and starting bit as
* the loop index.
* - Verify bit number is returned.
* - Call find_next_bit() with a starting bit > size. Verify returns size.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_find_next_bit(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_find_zero_area
*
* Description: Test the API bitmap_find_next_zero_area_off().
*
* Test Type: Feature, Boundary values
*
* Targets: bitmap_find_next_zero_area, bitmap_find_next_zero_area_off
*
* Input: None.
*
* Steps:
* - Loop through array of all zeros:
* - Call bitmap_find_next_zero_area() with:
* - array of zeros
* - size of array (in bits)
* - start value of loop index
* - size of bitmap as size of array - 1 (bit)
* - 0 for alignment parameters
* - Verify returns loop index.
* - Call bitmap_find_next_zero_area() with:
* - array of zeros
* - size of array (in bits)
* - start value of loop index
* - size of bitmap as 1 (bit)
* - 0 for alignment parameters
* - Verify returns loop index.
* - Call bitmap_find_next_zero_area() with:
* - array of zeros
* - size of array (in bits)
* - start value of 0
* - size of bitmap as size of array - loop index
* - 0 for alignment parameters
* - Verify returns 0.
* - Loop through array of all zeros:
* - Call bitmap_find_next_zero_area_off() with:
* - array of zeros
* - size of array (in bits)
* - start value of loop index
* - size of bitmap as size of array - 1 (bit)
* - 0 for alignment parameters
* - Verify returns loop index.
* - Call bitmap_find_next_zero_area_off() with:
* - array of zeros
* - size of array (in bits)
* - start value of loop index
* - size of bitmap as 1 (bit)
* - 0 for alignment parameters
* - Verify returns loop index.
* - Call bitmap_find_next_zero_area_off() with:
* - array of zeros
* - size of array (in bits)
* - start value of 0
* - size of bitmap as size of array - loop index
* - 0 for alignment parameters
* - Verify returns 0.
* - Loop through array with all bits set:
* - Inner loop from 0 to outer loop index:
* - Call bitmap_find_next_zero_area_off() with:
* - array with all bits set
* - size of array (in bits)
* - start value of outer loop index
* - size of bitmap as Inner loop index
* - 0 for alignment parameters
* - Verify returns bitmap array size.
* - Loop through array with alternating nibbles of 0's and 1's:
* - Inner loop from 0 to outer loop index:
* - Call bitmap_find_next_zero_area_off() with:
* - array of alternating nibbles
* - size of array (in bits)
* - start value of outer loop index
* - size of bitmap as Inner loop index
* - 0 for alignment parameters
* - Verify:
* - If inner loop is <= 4, returns result < size of array.
* - If inner loop > 4, returns size of array since bitmap would not fit.
* - Call bitmap_find_next_zero_area_off() with:
* - array of alternating nibbles
* - size of array (in bits)
* - start value of outer loop index
* - size of bitmap as Inner loop index modulo 4 + 1
* - 3 for alignment mask
* - 0 for alignment offset
* - Verify (result % 8 != 4)
* - Call bitmap_find_next_zero_area_off() with:
* - array of alternating nibbles
* - size of array (in bits)
* - start value of outer loop index
* - size of bitmap as Inner loop index modulo 2 + 1
* - 7 for alignment mask
* - 2 for alignment offset
* - Verify (result % 8 != 6)
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_find_zero_area(struct unit_module *m, struct gk20a *g, void *unused);
/**
* Test specification for: test_single_bitops
*
* Description: Test the APIs nvgpu_set_bit(), nvgpu_clear_bit(), and
* nvgpu_test_bit().
*
* Test Type: Feature
*
* Targets: nvgpu_set_bit, nvgpu_clear_bit, nvgpu_test_bit
*
* Input: None.
*
* Steps:
* - Loop through bits in an array, calling nvgpu_set_bit() for each iteration,
* which will set all the bits in the array.
* - Loop back through array and verify all bits are set in the array.
* - Loop through bits in an array, calling nvgpu_test_bit() for each iteration,
* and verify nvgpu_test_bit() returns true for each bit.
* - Loop through bits in an array, calling nvgpu_clear_bit() for each
* iteration, which will clear all the bits in the array.
* - Loop back through array and verify none of the bits are set in the array.
* - Loop through bits in an array, calling nvgpu_test_bit() for each iteration,
* and verify nvgpu_test_bit() returns false for each bit.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_single_bitops(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_bit_setclear
*
* Description: Test the APIs nvgpu_set_bit() and nvgpu_clear_bit().
*
* Test Type: Feature
*
* Targets: nvgpu_set_bit, nvgpu_clear_bit
*
* Input: Pointer to struct test_find_bit_args as function parameter.
* - The parameter test_find_bit_args is used to select between testing of:
* - nvgpu_clear_bit()
* - nvgpu_set_bit()
*
* Steps:
* - If testing nvgpu_clear_bit(), initialize array with all bits set.
* Otherwise, clear the array.
* - Loop through bits in an array, calling the API for each iteration,
* which will either clear or set all the bits in the array.
* - Loop back through array and verify all bits are set properly in the array.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_bit_setclear(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_test_and_setclear_bit
*
* Description: Test the APIs nvgpu_test_and_clear_bit() and
* nvgpu_test_and_set_bit().
*
* Test Type: Feature
*
* Targets: nvgpu_test_and_clear_bit, nvgpu_test_and_set_bit
*
* Input: Pointer to struct test_find_bit_args as function parameter.
* - The parameter test_find_bit_args is used to select between testing of:
* - nvgpu_test_and_clear_bit()
* - nvgpu_test_and_set_bit()
*
* Steps:
* - If testing nvgpu_test_and_clear_bit(), initialize array with all bits set.
* Otherwise, clear the array.
* - Loop through bits in an array:
* - Call the requested API for each iteration.
* - Verify if testing nvgpu_test_and_clear_bit(), it returns true since the
* bit was set above. Alternately, if testing nvgpu_test_and_set_bit(),
* verify, the call returns false.
* - Loop through bits in an array:
* - Call the 'inverse' API for each iteration. I.e. if the original parameter
* to the test was to test nvgpu_test_and_clear_bit(),
* call nvgpu_test_and_set_bit(), and vice versa.
* - Verify the API call returns the expected value based on if array should
* be all set or cleared.
* - Loop back through array and verify all bits are set properly in the array,
* which should be the original initialization value.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_test_and_setclear_bit(struct unit_module *m, struct gk20a *g,
void *__args);
/**
* Test specification for: test_bitmap_setclear
*
* Description: Test the APIs nvgpu_bitmap_clear() and nvgpu_bitmap_set().
*
* Test Type: Feature
*
* Targets: nvgpu_bitmap_clear, nvgpu_bitmap_set
*
* Input: Pointer to struct test_find_bit_args as function parameter.
* - The parameter test_find_bit_args is used to select between testing of:
* - nvgpu_bitmap_clear()
* - nvgpu_bitmap_set()
*
* Steps:
* - Loop through the bits of an array:
* - Inner loop from 0 to possible bitmap size
* (i.e. array size - outer loop bit):
* - Initialize the array to 0's if testing nvgpu_bitmap_set() or 1's if
* testing nvgpu_bitmap_clear().
* - Call the API with the array, starting at the bit in the outer loop,
* and the bitmap size of the inner loop.
* - Verify the bitmap is set/cleared properly in the array.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_bitmap_setclear(struct unit_module *m, struct gk20a *g, void *__args);
/**
* Test specification for: test_bitops_misc
*
* Description: Test the various macros implemented in bitops unit.
*
* Test Type: Feature
*
* Targets: BITS_TO_LONGS, BIT, GENMASK, for_each_set_bit
*
* Input: None
*
* Steps:
* - Invoke BITS_TO_LONGS for various bit values and confirm the return value
* is as expected.
* - Invoke GENMASK for various mask value settings. Confirm if the return
* value has only the requested bits set.
* - Invoke for_each_set_bit for a particular bit pattern. Confirm if the loop
* is executed only for set bit positions.
* - Invoke BIT macro for various bit positions in loop. Confirm if the bit
* positions are as requested.
*
* Output: Returns SUCCESS if all the macro invocations returns result as
* expected. Otherwise, the test returns FAIL.
*
*/
int test_bitops_misc(struct unit_module *m, struct gk20a *g, void *__args);
#endif /* UNIT_POSIX_BITOPS_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 = posix-bug.o
MODULE = posix-bug
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=posix-bug
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=posix-bug
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,186 @@
/*
* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* 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 <stdint.h>
#include <setjmp.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/bug.h>
#include <nvgpu/types.h>
#include "posix-bug.h"
/*
* Simple wrapper function to call BUG() or not. It was not strictly necessary
* to wrap the call to BUG() in a function but it better ressembles the way
* EXPECT_BUG is to be used in unit tests.
*/
static void bug_caller(struct unit_module *m, bool call)
{
if (call == true) {
unit_info(m, "Calling BUG()\n");
BUG();
} else {
unit_info(m, "Not calling BUG()\n");
}
}
/*
* Simple wrapper function to call BUG_ON() with condition.
*/
static void bug_on_caller(struct unit_module *m, bool cond)
{
BUG_ON(cond);
}
/*
* Test to ensure the EXPECT_BUG construct works as intended by making sure it
* behaves properly when BUG is called or not.
* In the event that EXPECT_BUG is completely broken, the call to BUG() would
* cause the unit to crash and report a failure correctly.
*/
int test_expect_bug(struct unit_module *m,
struct gk20a *g, void *args)
{
/* Make sure calls to BUG() are caught as intended. */
if (!EXPECT_BUG(bug_caller(m, true))) {
unit_err(m, "BUG() was not called but it was expected.\n");
return UNIT_FAIL;
} else {
unit_info(m, "BUG() was called as expected\n");
}
/* Make sure there are no false positives when BUG is not called. */
if (!EXPECT_BUG(bug_caller(m, false))) {
unit_info(m, "BUG() was not called as expected.\n");
} else {
unit_err(m, "BUG() was called but it was not expected.\n");
return UNIT_FAIL;
}
if (!EXPECT_BUG(bug_on_caller(m, true))) {
unit_err(m, "BUG_ON expected to invoke BUG()\n");
return UNIT_FAIL;
} else {
unit_info(m, "BUG_ON invoked BUG() as expected\n");
}
if (!EXPECT_BUG(bug_on_caller(m, false))) {
unit_info(m, "BUG_ON() skipped BUG invocation as expected\n");
} else {
unit_err(m, "BUG_ON invoked BUG but it was not expected()\n");
return UNIT_FAIL;
}
return UNIT_SUCCESS;
}
static bool cb_called = false;
static void bug_cb(void *arg)
{
jmp_buf *jmp_handler = arg;
cb_called = true;
longjmp(*jmp_handler, 1);
}
static bool other_cb_called = false;
static void other_bug_cb(void *arg)
{
other_cb_called = true;
}
int test_bug_cb(struct unit_module *m,
struct gk20a *g, void *args)
{
struct nvgpu_bug_cb callback = {0};
struct nvgpu_bug_cb other_callback = {0};
jmp_buf handler;
/* two callbacks */
callback.cb = bug_cb;
callback.arg = &handler;
other_callback.cb = other_bug_cb;
other_callback.arg = NULL;
nvgpu_bug_register_cb(&other_callback);
nvgpu_bug_register_cb(&callback);
if (setjmp(handler) == 0) {
BUG();
}
if (!other_cb_called || !cb_called) {
unit_err(m, "BUG() callback was not called.\n");
return UNIT_FAIL;
}
/* one callback */
other_cb_called = false;
nvgpu_bug_register_cb(&other_callback);
nvgpu_bug_register_cb(&callback);
nvgpu_bug_unregister_cb(&other_callback);
if (setjmp(handler) == 0) {
BUG();
}
if (other_cb_called) {
unit_err(m, "callback unregistration failed.\n");
return UNIT_FAIL;
}
return UNIT_SUCCESS;
}
int test_warn_msg(struct unit_module *m,
struct gk20a *g, void *args)
{
bool ret;
ret = nvgpu_posix_warn(0, "");
if (ret != 0) {
unit_return_fail(m, "nvgpu_posix_warn failed for cond 0\n");
}
ret = nvgpu_posix_warn(1, "");
if (ret != 1) {
unit_return_fail(m, "nvgpu_posix_warn failed for cond 1\n");
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_bug_tests[] = {
UNIT_TEST(expect_bug, test_expect_bug, NULL, 0),
UNIT_TEST(bug_cb, test_bug_cb, NULL, 0),
UNIT_TEST(warn_msg, test_warn_msg, NULL, 0),
};
UNIT_MODULE(posix_bug, posix_bug_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,119 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-bug
* @{
*
* Software Unit Test Specification for posix-bug
*/
#ifndef __UNIT_POSIX_BUG_H__
#define __UNIT_POSIX_BUG_H__
/**
* Test specification for test_expect_bug
*
* Description: Test the BUG implementation.
*
* Test Type: Feature
*
* Targets: nvgpu_posix_bug, dump_stack,
* BUG, BUG_ON, nvgpu_assert
*
* Inputs: None
*
* Steps:
* 1) Use the unit test framework specific EXPECT_BUG define to call BUG.
* 2) BUG should be called as expected, but the portion of BUG implementation
* which cannot be run in unit test framework will not be executed.
* 3) EXPECT_BUG is also tested to make sure that BUG is not called where it is
* not expected.
* 4) Steps 1 and 2 are also executed to test the macro BUG_ON.
*
* Output:
* The test returns PASS if BUG is called as expected based on the parameters
* passed and EXPECT_BUG handles it accordingly.
* The test returns FAIL if either BUG is not called as expected or if
* EXPECT_BUG indicates that a BUG call was made which was not requested by
* the test.
*
*/
int test_expect_bug(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_bug_cb
*
* Description: Test the bug callback functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_bug_register_cb, nvgpu_bug_unregister_cb,
* nvgpu_bug_cb_from_node
*
* Inputs: None
*
* Steps:
* 1) Register two callbacks for BUG.
* 2) Invoke BUG and check if both the callback functions are invoked as
* expected.
* 3) Register two callbacks for BUG again.
* 4) Remove one of the registered callbacks.
* 5) Invoke BUG and confirm if the unregistered callback is not invoked.
*
* Output:
* The test returns PASS if both the callbacks are invoked in the first
* invocation of the BUG and in the second invocation, only the registered
* callback is invoked and not the unregistered callback. Otherwise, the test
* returns FAIL.
*
*/
int test_bug_cb(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_warn_msg
*
* Description: Test the warn message functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_posix_warn
*
* Inputs: None
*
* Steps:
* 1) Call nvgpu_posix_warn function with cond as 0.
* 2) Check the return value from function nvgpu_posix_warn. If it is not
* equal to 0, return FAIL.
* 3) Call nvgpu_posix_warn function with cond as 1.
* 4) Check the return value from function nvgpu_posix_warn. If it is not
* equal to 1, return FAIL.
* 5) Return PASS.
*
* Output:
* The test returns PASS if both the calls of nvgpu_posix_warn function returns
* the expected return value. Otherwise, the test returns FAIL.
*
*/
int test_warn_msg(struct unit_module *m, struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_BUG_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 = posix-circbuf.o
MODULE = posix-circbuf
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-circbuf
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) 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-circbuf
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,95 @@
/*
* 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 <stdint.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/circ_buf.h>
#include "posix-circbuf.h"
#define BUFFER_SIZE 16UL
int test_circbufcnt(struct unit_module *m,
struct gk20a *g, void *args)
{
unsigned int i;
unsigned long head, tail, size, ret;
head = 0;
tail = 0;
size = BUFFER_SIZE;
for (i = 0; i < BUFFER_SIZE; i++) {
head = i;
ret = CIRC_CNT(head, tail, size);
if (ret != i) {
unit_return_fail(m, "CIRC_CNT failed %ld\n", ret);
}
}
head = BUFFER_SIZE - 1;
for (i = 0; i < BUFFER_SIZE; i++) {
tail = (BUFFER_SIZE - 1) - i;
ret = CIRC_CNT(head, tail, size);
if (ret != i) {
unit_return_fail(m, "CIRC_CNT failed %ld\n", ret);
}
}
head = BUFFER_SIZE/2;
tail = BUFFER_SIZE/2;
ret = CIRC_CNT(head, tail, size);
if (ret) {
unit_return_fail(m, "CIRC_CNT failed %ld\n", ret);
}
return UNIT_SUCCESS;
}
int test_circbufspace(struct unit_module *m,
struct gk20a *g, void *args)
{
unsigned int i;
unsigned long head, tail, size, ret;
tail = BUFFER_SIZE;
size = BUFFER_SIZE;
for (i = 0; i < BUFFER_SIZE; i++) {
head = i;
ret = CIRC_SPACE(head, tail, size);
if (ret != ((BUFFER_SIZE - 1) - i)) {
unit_return_fail(m, "CIRC_SPACE failed %ld\n", ret);
}
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_circbuf_tests[] = {
UNIT_TEST(circbufcnt, test_circbufcnt, NULL, 0),
UNIT_TEST(circbufspace, test_circbufspace, NULL, 0),
};
UNIT_MODULE(posix_circbuf, posix_circbuf_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,88 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-circbuf
* @{
*
* Software Unit Test Specification for posix-circbuf
*/
#ifndef UNIT_POSIX_CIRCBUF_H
#define UNIT_POSIX_CIRCBUF_H
/**
* Test specification for test_circbufcnt
*
* Description: Test the buffer count implementation.
*
* Test Type: Feature
*
* Targets: CIRC_CNT
*
* Inputs: None
*
* Steps:
* 1) Invoke CIRC_CNT in loop with head assigned with loop index value and
* tail as zero.
* 2) Check if the return value of buffer count is equal to loop index. Else
* return fail.
* 3) Invoke CIRC_CNT in loop with head assigned as maximum index and tail
* decreased according to the loop index value.
* 4) Check if the return value of buffer count is equal to loop index. Else
* return fail.
* 5) Invoke CIRC_CNT with both head and tail assigned with same value.
* 6) Check if the return value is equal to zero, else return fail.
* 7) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of CIRC_CNT returns the
* expected value as buffer count. Otherwise, test returns FAIL.
*/
int test_circbufcnt(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_circbufspace
*
* Description: Test the buffer space check implementation.
*
* Test Type: Feature
*
* Targets: CIRC_SPACE
*
* Inputs: None
*
* Steps:
* 1) Invoke CIRC_SPACE in loop with head assigned as loop index and
* tail as buffer size.
* 2) Check if the return value of buffer space is equal to the maximum
* entries that the buffer can hold minus loop index. Else
* return fail.
* 3) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of CIRC_SPACE returns the
* expected value as available buffer space. Otherwise, test returns FAIL.
*/
int test_circbufspace(struct unit_module *m, struct gk20a *g, void *args);
#endif /* UNIT_POSIX_CIRCBUF_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 = posix-cond.o
MODULE = posix-cond
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=posix-cond
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) 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=posix-cond
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,552 @@
/*
* 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 <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/cond.h>
#include <nvgpu/thread.h>
#include <nvgpu/timers.h>
#include "posix-cond.h"
#define MISMATCH_ERROR 1000
struct test_cond_args {
bool use_broadcast;
bool use_int;
bool use_wait_int;
bool use_wait_locked;
bool use_signal_locked;
bool use_timedwait;
bool use_condition;
};
struct unit_test_cond_data {
int use_broadcast;
int use_int;
int use_wait_int;
int use_wait_locked;
int use_signal_locked;
int use_timedwait;
int use_condition;
};
struct unit_test_cond_data test_data;
struct nvgpu_cond test_cond;
static struct test_cond_args signal_normal = {
.use_broadcast = false,
.use_int = false,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = false,
.use_timedwait = false,
.use_condition = false
};
static struct test_cond_args signal_int = {
.use_broadcast = false,
.use_int = true,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = false,
.use_timedwait = false,
.use_condition = false
};
static struct test_cond_args signal_locked = {
.use_broadcast = false,
.use_int = false,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = true,
.use_timedwait = false,
.use_condition = false
};
static struct test_cond_args broadcast_normal = {
.use_broadcast = true,
.use_int = false,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = false,
.use_timedwait = false,
.use_condition = false
};
static struct test_cond_args broadcast_int = {
.use_broadcast = true,
.use_int = true,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = false,
.use_timedwait = false,
.use_condition = false
};
static struct test_cond_args broadcast_locked = {
.use_broadcast = true,
.use_int = false,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = true,
.use_timedwait = false,
.use_condition = false
};
static struct test_cond_args timed_wait = {
.use_broadcast = false,
.use_int = false,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = false,
.use_timedwait = true,
.use_condition = false
};
static struct test_cond_args condition_wait = {
.use_broadcast = false,
.use_int = false,
.use_wait_int = false,
.use_wait_locked = false,
.use_signal_locked = false,
.use_timedwait = false,
.use_condition = true
};
static struct test_cond_args condition_wait_locked = {
.use_broadcast = false,
.use_int = false,
.use_wait_int = false,
.use_wait_locked = true,
.use_signal_locked = false,
.use_timedwait = false,
.use_condition = true
};
static struct test_cond_args condition_wait_int = {
.use_broadcast = false,
.use_int = false,
.use_wait_int = true,
.use_wait_locked = false,
.use_signal_locked = false,
.use_timedwait = false,
.use_condition = true
};
bool read_wait = 0;
bool bcst_read_wait = 0;
int read_status = 0;
int bcst_read_status = 0;
char test_code[4];
static int test_cond_write_thread(void *args)
{
int i;
struct unit_test_cond_data *data;
data = (struct unit_test_cond_data *)args;
while (!read_wait) {
usleep(10);
}
if (data->use_broadcast) {
while (!bcst_read_wait) {
usleep(10);
}
}
for (i = 0; i < 4; i++) {
test_code[i] = 0x55;
}
usleep(50);
read_wait = false;
if (data->use_broadcast) {
bcst_read_wait = false;
if (data->use_int) {
nvgpu_cond_broadcast_interruptible(&test_cond);
} else {
if (data->use_signal_locked) {
nvgpu_cond_lock(&test_cond);
nvgpu_cond_broadcast_locked(&test_cond);
nvgpu_cond_unlock(&test_cond);
} else {
nvgpu_cond_broadcast(&test_cond);
}
}
} else {
if (data->use_int) {
nvgpu_cond_signal_interruptible(&test_cond);
} else {
if (data->use_signal_locked) {
nvgpu_cond_lock(&test_cond);
nvgpu_cond_signal_locked(&test_cond);
nvgpu_cond_unlock(&test_cond);
} else {
nvgpu_cond_signal(&test_cond);
}
}
}
return 0;
}
static int test_cond_read_thread(void *args)
{
int ret;
int i;
unsigned int timeout;
struct unit_test_cond_data *data;
data = (struct unit_test_cond_data *)args;
if (data->use_timedwait) {
timeout = 50;
} else {
timeout = NVGPU_COND_WAIT_TIMEOUT_MAX_MS;
}
if (data->use_condition) {
read_wait = true;
if (data->use_wait_int) {
ret = NVGPU_COND_WAIT_INTERRUPTIBLE(&test_cond,
test_code[3] == 0x55, 0);
} else if (data->use_wait_locked) {
nvgpu_cond_lock(&test_cond);
ret = NVGPU_COND_WAIT_LOCKED(&test_cond,
test_code[3] == 0x55, 0);
nvgpu_cond_unlock(&test_cond);
} else {
ret = NVGPU_COND_WAIT(&test_cond,
test_code[3] == 0x55, 0);
}
if (ret != 0) {
read_status = ret;
}
} else {
nvgpu_cond_lock(&test_cond);
read_wait = true;
ret = nvgpu_cond_timedwait(&test_cond, &timeout);
if (ret != 0) {
read_status = ret;
nvgpu_cond_unlock(&test_cond);
return -1;
}
nvgpu_cond_unlock(&test_cond);
for (i = 0; i < 4; i++) {
if (test_code[i] != 0x55) {
read_status = MISMATCH_ERROR;
return -1;
}
}
}
return 0;
}
static int test_cond_bcst_read_thread(void *args)
{
int ret;
int i;
unsigned int timeout;
struct unit_test_cond_data *data;
data = (struct unit_test_cond_data *)args;
if (data->use_timedwait) {
timeout = 50;
} else {
timeout = NVGPU_COND_WAIT_TIMEOUT_MAX_MS;
}
nvgpu_cond_lock(&test_cond);
bcst_read_wait = true;
ret = nvgpu_cond_timedwait(&test_cond, &timeout);
if (ret != 0) {
bcst_read_status = ret;
nvgpu_cond_unlock(&test_cond);
return -1;
}
nvgpu_cond_unlock(&test_cond);
for (i = 0; i < 4; i++) {
if (test_code[i] != 0x55) {
bcst_read_status = MISMATCH_ERROR;
return -1;
}
}
return 0;
}
int test_cond_init_destroy(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
memset(&test_cond, 0, sizeof(struct nvgpu_cond));
ret = nvgpu_cond_init(&test_cond);
if (ret != 0) {
unit_return_fail(m, "Cond init failed\n");
}
if (test_cond.initialized != true) {
unit_return_fail(m, "Init flag not set\n");
}
nvgpu_cond_destroy(&test_cond);
if (test_cond.initialized != false) {
unit_return_fail(m, "Cond destroy failed\n");
}
return UNIT_SUCCESS;
}
int test_cond_bug(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
memset(&test_cond, 0, sizeof(struct nvgpu_cond));
if(!EXPECT_BUG(nvgpu_cond_signal(NULL))) {
unit_return_fail(m, "BUG not called for NULL cond var\n");
}
if(!EXPECT_BUG(nvgpu_cond_signal(&test_cond))) {
unit_return_fail(m,
"BUG not called for uninitialized cond var\n");
}
if(!EXPECT_BUG(nvgpu_cond_signal_interruptible(NULL))) {
unit_return_fail(m, "BUG not called for NULL cond var\n");
}
if(!EXPECT_BUG(nvgpu_cond_signal_interruptible(&test_cond))) {
unit_return_fail(m,
"BUG not called for uninitialized cond var\n");
}
if(!EXPECT_BUG(nvgpu_cond_destroy(NULL))) {
unit_return_fail(m, "BUG not called for NULL cond var\n");
}
if(!EXPECT_BUG(nvgpu_cond_signal_locked(NULL))) {
unit_return_fail(m, "BUG not called for NULL cond var\n");
}
if(!EXPECT_BUG(nvgpu_cond_signal_locked(&test_cond))) {
unit_return_fail(m,
"BUG not called for uninitialized cond var\n");
}
ret = nvgpu_cond_broadcast(NULL);
if (ret != -EINVAL) {
unit_return_fail(m, "NULL cond var not handled\n");
}
ret = nvgpu_cond_broadcast(&test_cond);
if (ret != -EINVAL) {
unit_return_fail(m, "Uninitialized cond var not handled\n");
}
ret = nvgpu_cond_broadcast_interruptible(NULL);
if (ret != -EINVAL) {
unit_return_fail(m, "NULL cond var not handled\n");
}
ret = nvgpu_cond_broadcast_interruptible(&test_cond);
if (ret != -EINVAL) {
unit_return_fail(m, "Uninitialized cond var not handled\n");
}
ret = nvgpu_cond_broadcast_locked(&test_cond);
if (ret != -EINVAL) {
unit_return_fail(m, "Uninitialized cond var not handled\n");
}
return UNIT_SUCCESS;
}
int test_cond_signal(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
struct nvgpu_thread thread_write, thread_read, thread_bcst_read;
struct test_cond_args *test_args = (struct test_cond_args *)args;
memset(&test_cond, 0, sizeof(struct nvgpu_cond));
memset(&test_code, 0, sizeof(test_code));
memset(&test_data, 0, sizeof(struct unit_test_cond_data));
ret = nvgpu_cond_init(&test_cond);
if (ret != 0) {
unit_return_fail(m, "Cond init failed\n");
}
test_data.use_broadcast = test_args->use_broadcast;
test_data.use_int = test_args->use_int;
test_data.use_wait_int = test_args->use_wait_int;
test_data.use_wait_locked = test_args->use_wait_locked;
test_data.use_signal_locked = test_args->use_signal_locked;
test_data.use_timedwait = test_args->use_timedwait;
test_data.use_condition = test_args->use_condition;
read_status = 0;
bcst_read_status = 0;
ret = nvgpu_thread_create(&thread_read, (void *)&test_data,
&test_cond_read_thread, "");
if (ret != 0) {
nvgpu_cond_destroy(&test_cond);
unit_return_fail(m, "Cond read thread fail\n");
}
if (test_args->use_broadcast) {
ret = nvgpu_thread_create(&thread_bcst_read, &test_data,
&test_cond_bcst_read_thread, "");
if (ret != 0) {
nvgpu_cond_destroy(&test_cond);
nvgpu_thread_stop(&thread_read);
nvgpu_thread_join(&thread_read);
unit_return_fail(m, "Cond bcst read thread fail\n");
}
}
ret = nvgpu_thread_create(&thread_write, &test_data,
&test_cond_write_thread, "");
if (ret != 0) {
nvgpu_cond_destroy(&test_cond);
nvgpu_thread_stop(&thread_read);
nvgpu_thread_join(&thread_read);
if (test_args->use_broadcast) {
nvgpu_thread_stop(&thread_bcst_read);
nvgpu_thread_stop(&thread_bcst_read);
}
unit_return_fail(m, "Cond write thread fail\n");
}
nvgpu_thread_join(&thread_write);
nvgpu_thread_join(&thread_read);
if (test_args->use_broadcast) {
nvgpu_thread_join(&thread_bcst_read);
}
if (read_status != 0) {
nvgpu_cond_destroy(&test_cond);
unit_return_fail(m, "Cond read status fail %d\n",
read_status);
}
if (test_args->use_broadcast) {
if (bcst_read_status != 0) {
nvgpu_cond_destroy(&test_cond);
unit_return_fail(m,
"Cond bcst read status fail %d\n",
bcst_read_status);
}
}
nvgpu_cond_destroy(&test_cond);
return UNIT_SUCCESS;
}
int test_cond_timeout(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
unsigned int timeout;
signed long ts_before, ts_after, delay;
memset(&test_cond, 0, sizeof(struct nvgpu_cond));
timeout = 10;
ret = nvgpu_cond_init(&test_cond);
if (ret != 0) {
unit_return_fail(m, "Cond init failed\n");
}
ts_before = nvgpu_current_time_us();
nvgpu_cond_lock(&test_cond);
ret = nvgpu_cond_timedwait(&test_cond, &timeout);
if (ret != ETIMEDOUT) {
nvgpu_cond_unlock(&test_cond);
nvgpu_cond_destroy(&test_cond);
unit_return_fail(m, "Cond timed wait return error %d\n", ret);
}
ts_after = nvgpu_current_time_us();
delay = ts_after - ts_before;
delay /= 1000;
if (delay < 10) {
nvgpu_cond_unlock(&test_cond);
nvgpu_cond_destroy(&test_cond);
unit_return_fail(m,
"Timed wait Duration incorrect\n");
}
nvgpu_cond_unlock(&test_cond);
nvgpu_cond_destroy(&test_cond);
return UNIT_SUCCESS;
}
struct unit_module_test posix_cond_tests[] = {
UNIT_TEST(init, test_cond_init_destroy, NULL, 0),
UNIT_TEST(bug_cond, test_cond_bug, NULL, 0),
UNIT_TEST(wait_signal, test_cond_signal, &signal_normal, 0),
UNIT_TEST(wait_signal_int, test_cond_signal, &signal_int, 0),
UNIT_TEST(wait_signal_locked, test_cond_signal, &signal_locked, 0),
UNIT_TEST(timedwait_signal, test_cond_signal, &timed_wait, 0),
UNIT_TEST(wait_broadcast, test_cond_signal, &broadcast_normal, 0),
UNIT_TEST(wait_broadcast_int, test_cond_signal, &broadcast_int, 0),
UNIT_TEST(wait_broadcast_locked, test_cond_signal, &broadcast_locked, 0),
UNIT_TEST(wait_condition, test_cond_signal, &condition_wait, 0),
UNIT_TEST(wait_condition_int, test_cond_signal, &condition_wait_int, 0),
UNIT_TEST(wait_condition_locked, test_cond_signal, &condition_wait_locked, 0),
UNIT_TEST(wait_timeout, test_cond_timeout, NULL, 0),
};
UNIT_MODULE(posix_cond, posix_cond_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,259 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-cond
* @{
*
* Software Unit Test Specification for posix-cond
*/
#ifndef __UNIT_POSIX_COND_H__
#define __UNIT_POSIX_COND_H__
/**
* Test specification for test_cond_init_destroy
*
* Description: Test cond init and cleanup routine.
*
* Test Type: Feature
*
* Targets: nvgpu_cond_init, nvgpu_cond_destroy
*
* Inputs:
* 1) Global instance of struct nvgpu_cond.
*
* Steps:
* 1) Reset the global instance of struct nvgpu_cond with 0s.
* 2) Call nvgpu_cond_init to initialise the condition variable.
* 3) Check the return value for any error.
* 4) If step 3 passes, confirm the initialisation of cond variable
* by checking the value of variable in struct nvgpu_cond.
* 5) Cleanup the condition variable by calling function nvgpu_cond_destroy.
* 6) Confirm the cleanup action by checking the value of variable inside
* struct nvgpu_cond
*
* Output:
* The test returns PASS if cond variable initialization and cleanup functions
* returns expected success values and internal variables in cond variable
* structure is initialised with proper values.
* The test returns FAIL if either initialisation or cleanup routine fails.
* It also returns FAIL if the internal variables in cond variable structure
* is not set with corresponding value for init and cleanup.
*
*/
int test_cond_init_destroy(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_cond_bug
*
* Description: Test NULL and uninitialized cond vars.
*
* Test Type: Feature, Error injection
*
* Inputs:
* 1) Global instance of struct nvgpu_cond.
*
* Steps:
* 1) Call the condition variable functions with NULL as input parameter.
* 2) Make sure that all the called functions either invoke BUG or return
* an error value for NULL value as input parameter.
* 3) Call the condition variable function with uninitialized condition
* variable as input parameter.
* 4) Make sure that all the called functions either invokes BUG or returns
* an error value for uninitialized condition variable passed as input
* parameter.
*
* Output:
* The test returns PASS if all the NULL and uninitialized input parameters
* are handled by the condition variable functions by either calling BUG or by
* returning an error value.
* The test returns FAIL if any of the NULL or uninitialized condition variable
* passed as input parameter is not handled as expected.
*
*/
int test_cond_bug(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_cond_signal
*
* Description: Functionalities of cond unit that are tested as
* part of this function are as follows,
* - Waiting and signaling using normal signaling, interruptible signaling
* and signaling protected by explicit acquire/release of the locks.
* - Waiting and signaling using normal broadcast, interruptible broadcast
* and broadcast protected by explicit acquire/release of the locks.
* - Waiting and signaling using a condition check.
*
* Test Type: Feature
*
* Targets: nvgpu_cond_signal, nvgpu_cond_signal_locked,
* nvgpu_cond_broadcast, nvgpu_cond_broadcast_locked,
* nvgpu_cond_signal_interruptible,
* nvgpu_cond_broadcast_interruptible,
* nvgpu_cond_lock, nvgpu_cond_unlock, nvgpu_cond_timedwait,
* NVGPU_COND_WAIT, NVGPU_COND_WAIT_LOCKED,
* NVGPU_COND_WAIT_INTERRUPTIBLE,
* NVGPU_COND_WAIT_TIMEOUT_LOCKED
*
* Inputs:
* 1) Global instance of struct nvgpu_cond.
* 2) Global array test_code.
* 3) Global instance of struct unit_test_cond_data.
* 4) Global variables read_status, bcst_read_status.
* 5) Global variables read_wait, bcst_read_wait.
* 6) Function argument of type pointer to struct test_cond_args.
*
* Steps:
* All the above mentioned functionalities are tested by this function based
* on the input arguments. Steps for various tests are as mentioned below,
*
* a) Wait and Signal
* Three threads are involved in this test case.
* A main thread which creates a write thread and a read thread and then
* waits for the created threads to exit.
*
* - Main Thread:
* 1) Main thread resets the global variables test_code, test_cond
* and test_data.
* 2) Initialise the condition variable by calling nvgpu_cond_init.
* 3) Return failure if the init function returns error.
* 4) Copy the test args into global instance of unit_test_cond_data.
* 5) Reset global variables read_status and bcst_read_status to 0.
* 6) Create the read thread.
* 7) Cleanup the initialised cond variable and return failure if read
* thread creation fails.
* 8) Create the write thread.
* 9) Cleanup the initialised cond variable, cancel the read thread and
* return failure if write thread creation fails.
* 10) Wait for both read and write thread to exit using pthread_join.
* 11) Check for global variable read_status and return FAIL if the value
* indicates an error.
* 12) Return test PASS.
*
* - Read Thread:
* 1) Set global variable read_wait as true. This is used by write thread
* to continue further.
* 2) Wait on the condition variable.
* 3) On getting signalled, check for the pattern in test_code.
* 4) If the data does not match the written value, update read_status
* with error code.
* 5) Return from the thread handler.
*
* - Write Thread:
* 1) Wait on global variable read_wait to be true before proceeding
* further.
* 2) Update the global array test_code with a defined value.
* 3) Reset read_wait to 0.
* 4) Signal the condition variable.
* 5) Return from the thread handler.
*
* b) Wait and Signal interruptible
* The steps followed are the same as case a. But the signaling API
* used by write thread in step 4 is nvgpu_cond_signal_interruptible.
* Although functionality wise both nvgpu_cond_signal and
* nvgpu_cond_signal_interruptible are same, this test just ensures
* better code coverage.
*
* c) Wait and Signal locked
* The steps followed are the same as case a. But the write thread
* needs to explicitly acquire the mutex lock before signalling the
* read thread. The lock has to be released explicitly once the signal
* API is called.
*
* d) Timed Wait and Signal
* The test differs from case a on the duration of time used to wait for
* the signal. In this case the wait is limited to a predefined duration of
* time rather than wait forever as it is in case a.
*
* e) Wait and Broadcast
* In broadcast test cases an extra read thread is created by the main
* thread. Both the read threads will get blocked on the condition variable.
* The write thread has to broadcast the signal, which should bring both
* the read threads out of blocked state. The main thread needs to wait for
* the extra read thread also to exit in this case.
*
* f) Wait and Broadcast interruptible
* The write thread uses the nvgpu_cond_broadcast_interruptible API to
* broadcast the signal.
*
* g) Wait and Broadcast locked
* The write thread has to explicitly acquire the lock before broadcasting
* the signal and needs to release the lock explicitly after broadcast.
*
* h) Wait on condition
* The read thread waits for a particular condition to be met, rather than
* just blocking on the condition variable.
*
* i) Wait on condition interruptible
* The read thread uses the interruptible version of wait in this scenario.
*
* j) Wait on condition locked
* The read thread needs to explicitly acquire the lock before issuing a wait
* on the condition variable. And also needs to explicitly release the lock
* after getting unblocked.
*
* Output:
* All the tests return PASS if the condition variable is properly signalled
* by the write thread and further verification of shared data shows a
* successful update from write thread with a predefined value.
* The tests return FAIL, if any of the above conditions are not met.
*
*/
int test_cond_signal(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_cond_timeout
*
* Description: Test time out for a condition variable wait.
*
* Test Type: Feature, Error injection
*
* Inputs:
* 1) Global instance of struct nvgpu_cond.
*
* Steps:
* 1) Initialize the condition variable.
* 2) Call the function nvgpu_cond_timedwait with a timeout value.
* 3) Check the return value from the function nvgpu_cond_timedwait. If the
* return value is not ETIMEDOUT, unlock the mutex associated with the
* condition variable then destroy the condition variable and return fail.
* 4) If the return value is ETIMEDOUT, check the actual duration of timed
* wait. If it is less than the requested timeout value, unlock the mutex
* associated with the condition variable then destroy the condition
* variable and return FAIL.
* 5) Unlock the mutex associated with the condition variable then destroy the
* condition variable and return pass.
*
* Output:
* The test returns PASS if the nvgpu_cond_timedwait function returns
* ETIMEDOUT error.
* The test returns FAIL if the return value from nvgpu_cond_timedwait function
* is not ETIMEDOUT.
*
*/
int test_cond_timeout(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_COND_H__ */

26
userspace/units/posix/env/Makefile vendored Normal file
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 = posix-env.o
MODULE = posix-env
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=posix-env
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

35
userspace/units/posix/env/Makefile.tmk vendored Normal file
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=posix-env
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

229
userspace/units/posix/env/posix-env.c vendored Normal file
View File

@@ -0,0 +1,229 @@
/*
* 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 <stdint.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/types.h>
/*
* Test if the passed type is signed. In the signed case this expression becomes
*
* x = 0;
* y = x - 1 = -1
*
* And -1 < 0 will be true. In the unsigned case, we rely on wrap around. We
* have the following
*
* x = 0U
* y = x - 1 = ~0 (i.e <TYPE>_MAX)
*
* Thus the expression y < x is false.
*/
#define IS_SIGNED_TYPE(__type__) \
({ \
__type__ x = (__type__)0; \
__type__ y = x - (__type__)1; \
y < x; \
})
/*
* Ensure that our sized types are of the correct size. Assumes an 8bit byte of
* course.
*/
static int sanity_test_sizes(struct unit_module *m,
struct gk20a *g, void *args)
{
size_t size_u8 = sizeof(u8);
size_t size_u16 = sizeof(u16);
size_t size_u32 = sizeof(u32);
size_t size_u64 = sizeof(u64);
size_t size_s8 = sizeof(s8);
size_t size_s16 = sizeof(s16);
size_t size_s32 = sizeof(s32);
size_t size_s64 = sizeof(s64);
/* Unsigned. */
if (size_u8 != 1U)
unit_return_fail(m,
"sizeof(u8) != 1 byte! (Actual size: %zu)\n",
size_u8);
if (size_u16 != 2U)
unit_return_fail(m,
"sizeof(u16) != 2 bytes! (Actual size: %zu)\n",
size_u16);
if (size_u32 != 4U)
unit_return_fail(m,
"sizeof(u32) != 4 bytes! (Actual size: %zu)\n",
size_u32);
if (size_u64 != 8U)
unit_return_fail(m,
"sizeof(u64) != 8 bytes! (Actual size: %zu)\n",
size_u64);
/* Signed. */
if (size_s8 != 1U)
unit_return_fail(m,
"sizeof(s8) != 1 byte! (Actual size: %zu)\n",
size_s8);
if (size_s16 != 2U)
unit_return_fail(m,
"sizeof(s16) != 2 bytes! (Actual size: %zu)\n",
size_s16);
if (size_s32 != 4U)
unit_return_fail(m,
"sizeof(s32) != 4 bytes! (Actual size: %zu)\n",
size_s32);
if (size_s64 != 8U)
unit_return_fail(m,
"sizeof(s64) != 8 bytes! (Actual size: %zu)\n",
size_s64);
return UNIT_SUCCESS;
}
/*
* Make sure that the signed types really are signed and that the unsigned types
* really are not.
*/
static int sanity_test_signage(struct unit_module *m,
struct gk20a *g, void *args)
{
if (!IS_SIGNED_TYPE(s8))
unit_return_fail(m, "s8 is not signed!\n");
if (!IS_SIGNED_TYPE(s16))
unit_return_fail(m, "s16 is not signed!\n");
if (!IS_SIGNED_TYPE(s32))
unit_return_fail(m, "s32 is not signed!\n");
if (!IS_SIGNED_TYPE(s64))
unit_return_fail(m, "s64 is not signed!\n");
if (IS_SIGNED_TYPE(u8))
unit_return_fail(m, "u8 is signed!\n");
if (IS_SIGNED_TYPE(u16))
unit_return_fail(m, "u16 is signed!\n");
if (IS_SIGNED_TYPE(u32))
unit_return_fail(m, "u32 is signed!\n");
if (IS_SIGNED_TYPE(u64))
unit_return_fail(m, "u64 is signed!\n");
return UNIT_SUCCESS;
}
/*
* Ensure that a u64 can hold a pointer since in some places we use a u64 to
* pass back a pointer value.
*/
static int sanity_test_ptr_in_u64(struct unit_module *m,
struct gk20a *g, void *args)
{
if (sizeof(u64) < sizeof(uintptr_t))
unit_return_fail(m,
"u64 size (%zu b) less than pointer size (%zu b)",
sizeof(u64), sizeof(uintptr_t));
return UNIT_SUCCESS;
}
static int sanity_test_endianness(struct unit_module *m,
struct gk20a *g, void *args)
{
u32 i;
u32 x = 0x12345678;
u8 *ptr_x_u8 = (u8 *)&x;
u16 *ptr_x_u16 = (u16 *)&x;
/*
* Print what endianness we have. For now we have not explicitly decided
* to support one or the other, but this will have to be determined
* eventually.
*
* We have just been lucky so far.
*/
unit_info(m, "u32 x = 0x%x\n", x);
for (i = 0; i < sizeof(u32) / sizeof(u16); i++) {
unit_info(m, " &x + %zu: 0x%04hx\n",
i * sizeof(u16), ptr_x_u16[i]);
}
unit_info(m, "u32 x = 0x%x\n", x);
for (i = 0; i < sizeof(u32); i++) {
unit_info(m, " &x + %u: 0x%02hhx\n", i, ptr_x_u8[i]);
}
switch (ptr_x_u8[0]) {
case 0x12:
unit_info(m, "Machine endianness: big\n");
break;
case 0x78:
unit_info(m, "Machine endianness: little\n");
break;
default:
unit_return_fail(m, "Machine endianness: middle/unknown ??\n");
}
return UNIT_SUCCESS;
}
static int sanity_test_type_max(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret = UNIT_SUCCESS;
u64 val;
val = (1ULL << 8) - 1;
if (val != U8_MAX) {
unit_err(m, "U8_MAX != %llu\n", val);
ret = UNIT_FAIL;
}
val = (1ULL << 16) - 1;
if (val != U16_MAX) {
unit_err(m, "U16_MAX != %llu\n", val);
ret = UNIT_FAIL;
}
val = (1ULL << 32) - 1;
if (val != U32_MAX) {
unit_err(m, "U32_MAX != %llu\n", val);
ret = UNIT_FAIL;
}
val = 0ULL - 1;
if (val != U64_MAX) {
unit_err(m, "U64_MAX != %llu\n", val);
ret = UNIT_FAIL;
}
return ret;
}
struct unit_module_test posix_env_tests[] = {
UNIT_TEST(sizes, sanity_test_sizes, NULL, 0),
UNIT_TEST(signage, sanity_test_signage, NULL, 0),
UNIT_TEST(endianness, sanity_test_endianness, NULL, 0),
UNIT_TEST(ptr_in_u64, sanity_test_ptr_in_u64, NULL, 0),
UNIT_TEST(type_max, sanity_test_type_max, NULL, 0),
};
UNIT_MODULE(posix_env, posix_env_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,28 @@
# 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 = posix-fault-injection.o \
posix-fault-injection-kmem.o \
posix-fault-injection-dma-alloc.o
MODULE = posix-fault-injection
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=posix-fault-injection
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,38 @@
################################### 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=posix-fault-injection
NVGPU_UNIT_SRCS=posix-fault-injection.c \
posix-fault-injection-kmem.c \
posix-fault-injection-dma-alloc.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,224 @@
/*
* 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/unit.h>
#include <unit/io.h>
#include <nvgpu/dma.h>
#include <nvgpu/nvgpu_mem.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include "posix-fault-injection-dma-alloc.h"
#define TEST_DEFAULT_SIZE 4096
static struct nvgpu_posix_fault_inj *dma_fi;
/*
* Used to make sure fault injection is disabled before running test
* If already enabled, prints warning and disables
*
* Returns false if unable to guarantee fault injection is disabled
*/
static bool verify_fi_disabled(struct unit_module *m)
{
if (nvgpu_posix_is_fault_injection_triggered(dma_fi)) {
unit_info(m, "Unexpected fault injection enabled\n");
}
/* force disabled in case it was in "delay" mode */
nvgpu_posix_enable_fault_injection(dma_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(dma_fi)) {
unit_err(m, "Unable to disable fault injection\n");
return false;
}
return true;
}
int test_dma_alloc_init(struct unit_module *m,
struct gk20a *g, void *__args)
{
dma_fi = nvgpu_dma_alloc_get_fault_injection();
if (dma_fi == NULL) {
return UNIT_FAIL;
} else {
return UNIT_SUCCESS;
}
}
int test_dma_alloc_fi_default(struct unit_module *m,
struct gk20a *g, void *__args)
{
struct nvgpu_mem mem = { };
int result;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* check default case, no fault injection */
result = nvgpu_dma_alloc(g, TEST_DEFAULT_SIZE, &mem);
if (result != 0) {
unit_err(m, "nvgpu_dma_alloc returned error when fault "
"injection disabled\n");
ret = UNIT_FAIL;
}
/* good housekeeping */
nvgpu_dma_free(g, &mem);
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(dma_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(dma_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "dma alloc fault injection test "
"failure\n");
}
return ret;
}
int test_dma_alloc_fi_enabled(struct unit_module *m,
struct gk20a *g, void *__args)
{
struct nvgpu_mem mem = { };
int result;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable fault injection immediately */
nvgpu_posix_enable_fault_injection(dma_fi, true, 0);
if (!nvgpu_posix_is_fault_injection_triggered(dma_fi)) {
unit_err(m, "unable to enable fault injection\n");
ret = UNIT_FAIL;
goto test_exit;
}
result = nvgpu_dma_alloc(g, TEST_DEFAULT_SIZE, &mem);
if (result == 0) {
unit_err(m, "nvgpu_dma_alloc returned success when fault "
"injection enabled\n");
nvgpu_dma_free(g, &mem);
ret = UNIT_FAIL;
}
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(dma_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(dma_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "dma alloc fault injection test "
"failure\n");
}
return ret;
}
int test_dma_alloc_fi_delayed_enable(struct unit_module *m,
struct gk20a *g, void *__args)
{
#define FAIL_AFTER 2
unsigned int call_count = 0;
struct nvgpu_mem mem[FAIL_AFTER+1] = { };
int result = 0;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable fault injection after delay */
nvgpu_posix_enable_fault_injection(dma_fi, true, FAIL_AFTER);
if (nvgpu_posix_is_fault_injection_triggered(dma_fi)) {
unit_err(m, "Fault injection errantly enabled too soon\n");
ret = UNIT_FAIL;
goto test_exit;
}
call_count = 1;
while (call_count <= (FAIL_AFTER+1)) {
result = nvgpu_dma_alloc(g, TEST_DEFAULT_SIZE,
&mem[call_count-1]);
if ((call_count <= FAIL_AFTER) && (result != 0U)) {
unit_err(m, "nvgpu_dma_alloc returned error when fault "
"injection disabled\n");
ret = UNIT_FAIL;
/* no reason to go on */
break;
} else if ((call_count > FAIL_AFTER) && (result == 0U)) {
unit_err(m, "nvgpu_dma_alloc returned success when "
"fault injection enabled\n");
ret = UNIT_FAIL;
/* no reason to go on */
break;
}
call_count++;
}
test_exit:
/* free allocations */
if (result != 0) {
/* the last alloc failed, so decrement before we start
* freeing
*/
call_count--;
}
while (call_count > 1) {
nvgpu_dma_free(g, &mem[call_count-1]);
call_count--;
}
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(dma_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(dma_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "dma alloc fault injection test "
"failure\n");
}
return ret;
}

View File

@@ -0,0 +1,116 @@
/*
* 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.
*/
#ifndef __UNIT_FAULT_INJECTION_DMA_ALLOC_H__
#define __UNIT_FAULT_INJECTION_DMA_ALLOC_H__
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-posix-fault-injection
* @{
*/
/**
* Test specification for: test_dma_alloc_init
*
* Description: Initialization required for dma alloc fault injection tests.
*
* Test Type: Other (Setup)
*
* Input: test_fault_injection_init() must have been called prior to this test.
*
* Steps:
* - Get the pointer to the dma alloc fault injection object.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_dma_alloc_init(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_dma_alloc_fi_default
*
* Description: This test simply tests the default case of fault injection
* disabled for calling dma alloc routines.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_dma_alloc_init() must have been
* called prior to this test.
*
* Steps:
* - Verify the dma alloc fault injection is disabled.
* - Call nvgpu_dma_alloc() verify the call succeeded.
* - Free the dma allocation.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_dma_alloc_fi_default(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_dma_alloc_fi_enabled
*
* Description: This test validates immediate fault injection for dma alloc
* routines.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_dma_alloc_init() must have been
* called prior to this test.
*
* Steps:
* - Enable dma alloc fault injection immediately.
* - Call nvgpu_dma_alloc() and verify an error is returned.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_dma_alloc_fi_enabled(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_dma_alloc_fi_delayed_enable
*
* Description: This test validates delayed enable of fault injection for dma
* alloc APIs.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_dma_alloc_init() must have been
* called prior to this test.
*
* Steps:
* - Enable dma alloc fault injection for after 2 calls.
* - Loop calling nvgpu_dma_alloc() and verify success until the 3rd call.
* - Cleanup the dma allocation.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_dma_alloc_fi_delayed_enable(struct unit_module *m,
struct gk20a *g, void *__args);
#endif /* __UNIT_FAULT_INJECTION_DMA_ALLOC_H__ */

View File

@@ -0,0 +1,512 @@
/*
* 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/unit.h>
#include <unit/io.h>
#include <nvgpu/kmem.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include "posix-fault-injection-kmem.h"
#define TEST_DEFAULT_CACHE_SIZE 1024
#define TEST_DEFAULT_KMALLOC_SIZE 1024
static struct nvgpu_posix_fault_inj *kmem_fi;
/*
* Used to make sure fault injection is disabled before running test
* If already enabled, prints warning and disables
*
* Returns false if unable to guarantee fault injection is disabled
*/
static bool verify_fi_disabled(struct unit_module *m)
{
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_info(m, "Unexpected fault injection enabled\n");
}
/* force disabled in case it was in "delay" mode */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Unable to disable fault injection\n");
return false;
}
return true;
}
int test_kmem_init(struct unit_module *m,
struct gk20a *g, void *__args)
{
kmem_fi = nvgpu_kmem_get_fault_injection();
if (kmem_fi == NULL) {
return UNIT_FAIL;
} else {
return UNIT_SUCCESS;
}
}
int test_kmem_cache_fi_default(struct unit_module *m,
struct gk20a *g, void *__args)
{
struct nvgpu_kmem_cache *kmem_cache;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* check default case */
kmem_cache = nvgpu_kmem_cache_create(g, TEST_DEFAULT_CACHE_SIZE);
if (kmem_cache == NULL) {
unit_err(m, "nvgpu_kmem_cache_create returned NULL when fault "
"injection disabled\n");
ret = UNIT_FAIL;
}
nvgpu_kmem_cache_destroy(kmem_cache);
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test "
"failure\n");
}
return ret;
}
int test_kmem_cache_fi_enabled(struct unit_module *m,
struct gk20a *g, void *__args)
{
struct nvgpu_kmem_cache *kmem_cache;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable faults */
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
if (!nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Unable to enable fault injection\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* create cache and verify error */
kmem_cache = nvgpu_kmem_cache_create(g, TEST_DEFAULT_CACHE_SIZE);
if (kmem_cache != NULL) {
unit_err(m, "nvgpu_kmem_cache_create returned pointer when "
"fault injection enabled\n");
ret = UNIT_FAIL;
}
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test failure"
"\n");
}
return ret;
}
int test_kmem_cache_fi_delayed_enable(struct unit_module *m,
struct gk20a *g, void *__args)
{
struct nvgpu_kmem_cache *kmem_cache;
int *ptr1, *ptr2;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable faults after 2 calls */
nvgpu_posix_enable_fault_injection(kmem_fi, true, 2);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Fault injection errantly enabled too soon\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* first call should pass */
kmem_cache = nvgpu_kmem_cache_create(g, TEST_DEFAULT_CACHE_SIZE);
if (kmem_cache == NULL) {
unit_err(m, "nvgpu_kmem_cache_create returned NULL when fault "
"injection disabled\n");
/* no reason to go on */
goto test_exit;
ret = UNIT_FAIL;
}
/* second call should pass */
ptr1 = (int *)nvgpu_kmem_cache_alloc(kmem_cache);
if (ptr1 == NULL) {
unit_err(m, "nvgpu_kmem_cache_alloc returned NULL when fault "
"injection disabled\n");
ret = UNIT_FAIL;
}
/* third call should fail */
ptr2 = (int *)nvgpu_kmem_cache_alloc(kmem_cache);
if (ptr2 != NULL) {
unit_err(m, "nvgpu_kmem_cache_alloc returned pointer when "
"fault injection enabled\n");
nvgpu_kmem_cache_free(kmem_cache, ptr2);
ret = UNIT_FAIL;
}
/* good housekeeping */
nvgpu_kmem_cache_free(kmem_cache, ptr1);
nvgpu_kmem_cache_destroy(kmem_cache);
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test failure"
"\n");
}
return ret;
}
int test_kmem_cache_fi_delayed_disable(struct unit_module *m,
struct gk20a *g, void *__args)
{
struct nvgpu_kmem_cache *kmem_cache;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable faults now */
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
if (!nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Unable to enable fault injection\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* disable faults after 1 call */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 1);
if (!nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Fault injection errantly disabled too soon\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* first call should fail */
kmem_cache = nvgpu_kmem_cache_create(g, TEST_DEFAULT_CACHE_SIZE);
if (kmem_cache != NULL) {
unit_err(m, "nvgpu_kmem_cache_create returned pointer when "
"fault injection enabled\n");
ret = UNIT_FAIL;
}
/* second call should pass */
kmem_cache = nvgpu_kmem_cache_create(g, TEST_DEFAULT_CACHE_SIZE);
if (kmem_cache == NULL) {
unit_err(m, "nvgpu_kmem_cache_create returned NULL when fault "
"injection disabled\n");
ret = UNIT_FAIL;
}
/* good housekeeping */
nvgpu_kmem_cache_destroy(kmem_cache);
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test failure"
"\n");
}
return ret;
}
int test_kmem_kmalloc_fi_default(struct unit_module *m,
struct gk20a *g, void *__args)
{
int *ptr;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* check default case */
ptr = (int *)nvgpu_kmalloc(g, TEST_DEFAULT_KMALLOC_SIZE);
if (ptr == NULL) {
unit_err(m, "nvgpu_kmalloc returned NULL when fault injection "
"disabled\n");
ret = UNIT_FAIL;
}
/* good housekeeping */
nvgpu_kfree(g, ptr);
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test failure"
"\n");
}
return ret;
}
int test_kmem_kmalloc_fi_enabled(struct unit_module *m,
struct gk20a *g, void *__args)
{
int *ptr;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable faults */
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
if (!nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Unable to enable fault injection\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* call kmalloc and verify error */
ptr = (int *)nvgpu_kmalloc(g, TEST_DEFAULT_KMALLOC_SIZE);
if (ptr != NULL) {
unit_err(m, "nvgpu_kmalloc returned pointer when fault "
"injection enabled\n");
ret = UNIT_FAIL;
}
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test failure"
"\n");
}
return ret;
}
int test_kmem_kmalloc_fi_delayed_enable(struct unit_module *m,
struct gk20a *g, void *__args)
{
const unsigned int fail_after = 2;
int *ptrs[fail_after+1];
unsigned int call_count;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable faults after "fail_after" calls */
nvgpu_posix_enable_fault_injection(kmem_fi, true, fail_after);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Fault injection errantly enabled too soon\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
call_count = 1;
while (call_count <= (fail_after + 1)) {
ptrs[call_count-1] = nvgpu_kmalloc(g,
TEST_DEFAULT_KMALLOC_SIZE);
if ((call_count <= fail_after) &&
(ptrs[call_count-1] == NULL)) {
unit_err(m, "nvgpu_kmalloc returned NULL when fault "
"injection disabled\n");
ret = UNIT_FAIL;
/* no reason to go on */
break;
} else if ((call_count > fail_after) &&
(ptrs[call_count-1] != NULL)) {
unit_err(m, "nvgpu_kmalloc returned pointer when fault "
"injection enabled\n");
ret = UNIT_FAIL;
/* no reason to go on */
break;
}
call_count++;
}
/* good housekeeping */
while (--call_count >= 1) {
if (ptrs[call_count-1] != NULL) {
nvgpu_kfree(g, ptrs[call_count-1]);
}
}
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test failure"
"\n");
}
return ret;
}
int test_kmem_kmalloc_fi_delayed_disable(struct unit_module *m,
struct gk20a *g, void *__args)
{
const unsigned int pass_after = 2;
int *ptrs[pass_after+1];
unsigned int call_count;
int ret = UNIT_SUCCESS;
if (!verify_fi_disabled(m)) {
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* enable faults now */
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
if (!nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Unable to enable fault injection\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
/* disable faults after "pass_after" calls */
nvgpu_posix_enable_fault_injection(kmem_fi, false, pass_after);
if (!nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "Fault injection errantly disabled too soon\n");
ret = UNIT_FAIL;
/* no reason to go on */
goto test_exit;
}
call_count = 1;
while (call_count <= (pass_after + 1)) {
ptrs[call_count-1] = nvgpu_kmalloc(g,
TEST_DEFAULT_KMALLOC_SIZE);
if ((call_count <= pass_after) &&
(ptrs[call_count-1] != NULL)) {
unit_err(m, "nvgpu_kmalloc returned pointer when fault "
"injection enabled\n");
ret = UNIT_FAIL;
/* no reason to go on */
break;
} else if ((call_count > pass_after) &&
(ptrs[call_count-1] == NULL)) {
unit_err(m, "nvgpu_kmalloc returned NULL when fault "
"injection disabled\n");
ret = UNIT_FAIL;
/* no reason to go on */
break;
}
call_count++;
}
/* good housekeeping */
while (--call_count >= 1) {
if (ptrs[call_count-1] != NULL) {
nvgpu_kfree(g, ptrs[call_count-1]);
}
}
test_exit:
/* disable faults upon exit */
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
if (nvgpu_posix_is_fault_injection_triggered(kmem_fi)) {
unit_err(m, "unable to disable fault injection\n");
ret = UNIT_FAIL;
}
if (ret != UNIT_SUCCESS) {
unit_return_fail(m, "kmem cache fault injection test failure"
"\n");
}
return ret;
}

View File

@@ -0,0 +1,234 @@
/*
* 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.
*/
#ifndef __UNIT_FAULT_INJECTION_KMEM_H__
#define __UNIT_FAULT_INJECTION_KMEM_H__
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-posix-fault-injection
* @{
*/
/**
* Test specification for: test_kmem_init
*
* Description: Initialization required for kmem fault injection tests.
*
* Test Type: Other (Setup)
*
* Input: test_fault_injection_init() must have been called prior to this test.
*
* Steps:
* - Get the pointer to the kmem fault injection object.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_init(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_cache_fi_default
*
* Description: This test simply tests the default case of fault injection
* disabled for calling kmem cache routines.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Verify the kmem fault injection is disabled.
* - Create a kmem cache object and verify the return is non-NULL.
* - Destroy the kmem cache object.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_cache_fi_default(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_cache_fi_enabled
*
* Description: This test validates immediate fault injection for kmem cache
* create.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Enable kmem fault injection immediately.
* - Create a kmem cache object and verify the return is NULL, indicating
* failure.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_cache_fi_enabled(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_cache_fi_delayed_enable
*
* Description: This test validates delayed enable of fault injection for kmem
* cache APIs.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Enable kmem fault injection for after 2 calls.
* - Create a kmem cache object and verify the return is non-NULL, indicating
* pass.
* - Allocate from the kmem cache object and verify the 1st call passes.
* - Allocate from the kmem cache object and verify the 2nd call fails.
* - Cleanup the allocated cache.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_cache_fi_delayed_enable(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_cache_fi_delayed_disable
*
* Description: This test validates delayed disable of fault injection for kmem
* cache APIs.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Enable kmem fault injection immediately.
* - Disable fault injection for after 1 call.
* - Create a kmem cache object and verify the return is NULL, indicating fail.
* - Create a kmem cache object and verify the return is non-NULL for the 2nd
* call, indicating pass and the fault injection was disabled.
* - Cleanup the allocated cache.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_cache_fi_delayed_disable(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_kmalloc_fi_default
*
* Description: This test simply tests the default case of fault injection
* disabled for calling kmem kmalloc routines.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Verify the kmem fault injection is disabled.
* - Allocate memory with nvgpu_kmalloc() and verify the call passed.
* - Free the kmem kmalloc memory.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_kmalloc_fi_default(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_kmalloc_fi_enabled
*
* Description: This test validates immediate fault injection for kmem kmalloc.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Enable kmem fault injection immediately.
* - Allocate memory with nvgpu_kmalloc() and verify the result is NULL,
* indicating fail.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_kmalloc_fi_enabled(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_kmalloc_fi_delayed_enable
*
* Description: This test validates delayed enable of fault injection for kmem
* kmalloc APIs.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Enable kmem fault injection for after 2 calls.
* - Call nvgpu_kmalloc() 3 times and verify it fails only on the 3rd call.
* - Cleanup the allocated memory.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_kmalloc_fi_delayed_enable(struct unit_module *m,
struct gk20a *g, void *__args);
/**
* Test specification for: test_kmem_kmalloc_fi_delayed_disable
*
* Description: This test validates delayed disable of fault injection for kmem
* kalloc APIs.
*
* Test Type: Feature Based
*
* Input: test_fault_injection_init() & test_kmem_init() must have been called
* prior to this test.
*
* Steps:
* - Enable kmem fault injection immediately.
* - Disable fault injection for after 2 calls.
* - Call nvgpu_kmalloc() in a loop and verify it fails until the 3rd call.
* - Cleanup the allocated cache.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_kmem_kmalloc_fi_delayed_disable(struct unit_module *m,
struct gk20a *g, void *__args);
#endif /* __UNIT_FAULT_INJECTION_KMEM_H__ */

View File

@@ -0,0 +1,64 @@
/*
* 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 <nvgpu/enabled.h>
#include <unit/unit.h>
#include <unit/io.h>
#include "posix-fault-injection.h"
#include "posix-fault-injection-kmem.h"
#include "posix-fault-injection-dma-alloc.h"
int test_fault_injection_init(struct unit_module *m,
struct gk20a *g, void *__args)
{
nvgpu_set_enabled(g, NVGPU_MM_UNIFIED_MEMORY, true);
return UNIT_SUCCESS;
}
struct unit_module_test fault_injection_tests[] = {
UNIT_TEST(fault_injection_init, test_fault_injection_init, NULL, 0),
UNIT_TEST(init, test_kmem_init, NULL, 0),
UNIT_TEST(cache_default, test_kmem_cache_fi_default, NULL, 0),
UNIT_TEST(cache_enabled, test_kmem_cache_fi_enabled, NULL, 0),
UNIT_TEST(cache_delayed_enable, test_kmem_cache_fi_delayed_enable,
NULL, 0),
UNIT_TEST(cache_delayed_disable, test_kmem_cache_fi_delayed_disable,
NULL, 0),
UNIT_TEST(kmalloc_default, test_kmem_kmalloc_fi_default, NULL, 0),
UNIT_TEST(kmalloc_enabled, test_kmem_kmalloc_fi_enabled, NULL, 0),
UNIT_TEST(kmalloc_delayed_enable,
test_kmem_kmalloc_fi_delayed_enable, NULL, 0),
UNIT_TEST(kmalloc_delayed_disable,
test_kmem_kmalloc_fi_delayed_disable, NULL, 0),
UNIT_TEST(dma_alloc_init, test_dma_alloc_init, NULL, 0),
UNIT_TEST(dma_alloc_default, test_dma_alloc_fi_default, NULL, 0),
UNIT_TEST(dma_alloc_enabled, test_dma_alloc_fi_enabled, NULL, 0),
UNIT_TEST(dma_alloc_delayed_enable, test_dma_alloc_fi_delayed_enable,
NULL, 0),
};
UNIT_MODULE(fault_injection, fault_injection_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,54 @@
/*
* 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_FAULT_INJECTION_H
#define UNIT_FAULT_INJECTION_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-posix-fault-injection
* @{
*
* Software Unit Test Specification for posix-fault-injection
*/
/**
* Test specification for: test_fault_injection_init
*
* Description: General initialization required for posix fault injection tests.
*
* Test Type: Other (Setup)
*
* Input: None
*
* Steps:
* - Set the enabled flag NVGPU_MM_UNIFIED_MEMORY flag required for the mm unit
* to function properly for these tests.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_fault_injection_init(struct unit_module *m,
struct gk20a *g, void *__args);
#endif /* UNIT_FAULT_INJECTION_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 = posix-kmem.o
MODULE = posix-kmem
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=posix-kmem
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=posix-kmem
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,257 @@
/*
* 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 <stdlib.h>
#include <unistd.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/kmem.h>
#include "posix-kmem.h"
#define KMEM_TEST_CACHE_SIZE 512
#define KMEM_TEST_ALLOC_SIZE 256
#define KMEM_TEST_CALLOC_COUNT 4
struct nvgpu_kmem_cache {
struct gk20a *g;
size_t size;
char name[128];
};
int test_kmem_cache_create(struct unit_module *m,
struct gk20a *g, void *args)
{
struct nvgpu_kmem_cache *test_cache;
test_cache = nvgpu_kmem_cache_create(g, KMEM_TEST_CACHE_SIZE);
if (test_cache == NULL) {
unit_return_fail(m, "Kmem cache create failed\n");
}
if (test_cache->size != KMEM_TEST_CACHE_SIZE) {
nvgpu_kmem_cache_destroy(test_cache);
unit_return_fail(m, "Kmem cache size mismatch\n");
} else if (test_cache->g != g) {
nvgpu_kmem_cache_destroy(test_cache);
unit_return_fail(m, "Kmem cache g structure mismatch\n");
}
nvgpu_kmem_cache_destroy(test_cache);
return UNIT_SUCCESS;
}
int test_kmem_cache_alloc(struct unit_module *m,
struct gk20a *g, void *args)
{
struct nvgpu_kmem_cache *test_cache;
void *test_ptr = NULL;
test_cache = nvgpu_kmem_cache_create(g, KMEM_TEST_CACHE_SIZE);
if (test_cache == NULL) {
unit_return_fail(m, "Kmem alloc cache create failed\n");
}
if (test_cache->size != KMEM_TEST_CACHE_SIZE) {
nvgpu_kmem_cache_destroy(test_cache);
unit_return_fail(m, "Kmem alloc cache size mismatch\n");
} else if (test_cache->g != g) {
nvgpu_kmem_cache_destroy(test_cache);
unit_return_fail(m, "Kmem alloc cache g structure mismatch\n");
}
test_ptr = nvgpu_kmem_cache_alloc(test_cache);
if (test_ptr == NULL) {
nvgpu_kmem_cache_destroy(test_cache);
unit_return_fail(m, "Kmem cache alloc failed\n");
}
nvgpu_kmem_cache_free(test_cache, test_ptr);
nvgpu_kmem_cache_destroy(test_cache);
return UNIT_SUCCESS;
}
int test_kmem_kmalloc(struct unit_module *m,
struct gk20a *g, void *args)
{
void *test_ptr;
test_ptr = nvgpu_kmalloc_impl(g, KMEM_TEST_ALLOC_SIZE, NULL);
if (test_ptr == NULL) {
unit_return_fail(m, "Kmalloc failed\n");
}
nvgpu_kfree_impl(g, test_ptr);
return UNIT_SUCCESS;
}
int test_kmem_kzalloc(struct unit_module *m,
struct gk20a *g, void *args)
{
void *test_ptr;
char *check_ptr;
int i;
test_ptr = nvgpu_kzalloc_impl(g, KMEM_TEST_ALLOC_SIZE, NULL);
if (test_ptr == NULL) {
unit_return_fail(m, "Kzalloc failed\n");
}
check_ptr = (char *)test_ptr;
for (i = 0; i < KMEM_TEST_ALLOC_SIZE; i++) {
if (*check_ptr != 0) {
nvgpu_kfree_impl(g, (void *)test_ptr);
unit_return_fail(m, "Non zero memory in Kzalloc\n");
}
check_ptr++;
}
nvgpu_kfree_impl(g, test_ptr);
return UNIT_SUCCESS;
}
int test_kmem_kcalloc(struct unit_module *m,
struct gk20a *g, void *args)
{
void *test_ptr;
char *check_ptr;
int i;
test_ptr = nvgpu_kcalloc_impl(g, KMEM_TEST_ALLOC_SIZE,
KMEM_TEST_CALLOC_COUNT, NULL);
if (test_ptr == NULL) {
unit_return_fail(m, "Kcalloc failed\n");
}
check_ptr = (char *)test_ptr;
for (i = 0; i < (KMEM_TEST_ALLOC_SIZE * KMEM_TEST_CALLOC_COUNT); i++) {
if (*check_ptr != 0) {
nvgpu_kfree_impl(g, (void *)test_ptr);
unit_return_fail(m, "Non zero memory in Kcalloc\n");
}
check_ptr++;
}
nvgpu_kfree_impl(g, test_ptr);
return UNIT_SUCCESS;
}
int test_kmem_virtual_alloc(struct unit_module *m,
struct gk20a *g, void *args)
{
void *test_ptr;
char *check_ptr;
int i;
test_ptr = nvgpu_vmalloc_impl(g, KMEM_TEST_ALLOC_SIZE, NULL);
if (test_ptr == NULL) {
unit_return_fail(m, "Vmalloc failed\n");
}
nvgpu_vfree_impl(g, test_ptr);
test_ptr = nvgpu_vzalloc_impl(g, KMEM_TEST_ALLOC_SIZE, NULL);
if (test_ptr == NULL) {
unit_return_fail(m, "Vzalloc failed\n");
}
check_ptr = (char *)test_ptr;
for (i = 0; i < KMEM_TEST_ALLOC_SIZE; i++) {
if (*check_ptr != 0) {
nvgpu_vfree_impl(g, (void *)test_ptr);
unit_return_fail(m,
"Non Zero entry in vzalloc memory\n");
}
check_ptr++;
}
nvgpu_vfree_impl(g, test_ptr);
return UNIT_SUCCESS;
}
int test_kmem_big_alloc(struct unit_module *m,
struct gk20a *g, void *args)
{
void *test_ptr;
char *check_ptr;
int i;
test_ptr = nvgpu_big_alloc_impl(g, KMEM_TEST_ALLOC_SIZE, false);
if (test_ptr == NULL) {
unit_return_fail(m, "Big alloc failed\n");
}
nvgpu_big_free(g, test_ptr);
test_ptr = nvgpu_big_alloc_impl(g, KMEM_TEST_ALLOC_SIZE, true);
if (test_ptr == NULL) {
unit_return_fail(m, "Big clear alloc failed\n");
}
check_ptr = (char *)test_ptr;
for (i = 0; i < KMEM_TEST_ALLOC_SIZE; i++) {
if (*check_ptr != 0) {
nvgpu_big_free(g, (void *)test_ptr);
unit_return_fail(m,
"Non Zero entry in big clear alloc memory\n");
}
check_ptr++;
}
nvgpu_big_free(g, test_ptr);
return UNIT_SUCCESS;
}
struct unit_module_test posix_kmem_tests[] = {
UNIT_TEST(cache_create, test_kmem_cache_create, NULL, 0),
UNIT_TEST(cache_alloc, test_kmem_cache_alloc, NULL, 0),
UNIT_TEST(kmalloc_test, test_kmem_kmalloc, NULL, 0),
UNIT_TEST(kzalloc_test, test_kmem_kzalloc, NULL, 0),
UNIT_TEST(kcalloc_test, test_kmem_kcalloc, NULL, 0),
UNIT_TEST(virtual_alloc, test_kmem_virtual_alloc, NULL, 0),
UNIT_TEST(big_alloc, test_kmem_big_alloc, NULL, 0),
};
UNIT_MODULE(posix_kmem, posix_kmem_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,258 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-kmem
* @{
*
* Software Unit Test Specification for posix-kmem
*/
#ifndef __UNIT_POSIX_KMEM_H__
#define __UNIT_POSIX_KMEM_H__
/**
* Test specification for test_kmem_cache_create
*
* Description: Test the creation of kmem cache.
*
* Test Type: Feature
*
* Targets: nvgpu_kmem_cache_create, nvgpu_kmem_cache_destroy
*
* Inputs:
* 1) GPU driver struct g.
* 2) Global define for cache size to alloc.
*
* Steps:
* 1) Call nvgpu_kmem_cache_create with cache size as a parameter.
* 2) Check the return value from cache create function. If the return value
* is NULL, return test FAIL.
* 3) Check if the size value of the created cache is equal to the requested
* size, if not destroy the cache and return FAIL.
* 4) Check if the g struct of the created cache is equal to the g struct
* instance passed to the cache creation API, if not destroy the cache and
* return FAIL.
* 5) Destroy the created cache and return PASS.
*
* Output:
* The test returns PASS if the cache is created successfully and the size and
* g struct of the cache matches with the passed arguments. Otherwise the test
* returns FAIL.
*
*/
int test_kmem_cache_create(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_kmem_cache_alloc
*
* Description: Test the allocation of memory from kmem cache.
*
* Test Type: Feature
*
* Targets: nvgpu_kmem_cache_create, nvgpu_kmem_cache_alloc,
* nvgpu_kmem_cache_free, nvgpu_kmem_cache_destroy
*
* Inputs:
* 1) GPU driver struct g.
* 2) Global define for cache size to alloc.
*
* Steps:
* 1) Call nvgpu_kmem_cache_create with cache size as a parameter.
* 2) Check the return value from cache create function. If the return value
* is NULL, return test FAIL.
* 3) Check if the size value of the created cache is equal to the requested
* size, if not destroy the cache and return FAIL.
* 4) Check if the g struct of the created cache is equal to the g struct
* instance passed to the cache creation API, if not destroy the cache and
* return FAIL.
* 5) Call nvgpu_kmem_cache_alloc to alloc memory from the created cache.
* 6) Check the return value from cache alloc function. If the return value
* is NULL, destroy the cache and return test FAIL.
* 7) Free the allocated memory and destroy the cache, and return PASS.
*
* Output:
* The test returns PASS if the cache creation and allocation of memory from
* the cache is successful. Otherwise, return FAIL.
*
*/
int test_kmem_cache_alloc(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_kmem_kmalloc
*
* Description: Test the allocation of memory using kmalloc.
*
* Test Type: Feature
*
* Targets: nvgpu_kmalloc_impl, nvgpu_kfree_impl
*
* Inputs:
* 1) GPU driver struct g.
* 2) Global define for size to alloc.
*
* Steps:
* 1) Call nvgpu_kmalloc_impl with size as a parameter.
* 2) Check the return value from nvgpu_kmalloc_impl function. If the return
* value is NULL, return test FAIL.
* 3) Free the allocated memory.
* 4) Return PASS.
*
* Output:
* The test returns PASS if the memory is successfully allocated. Otherwise,
* the test returns FAIL.
*/
int test_kmem_kmalloc(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_kmem_kzalloc
*
* Description: Test the allocation of memory using kzalloc.
*
* Test Type: Feature
*
* Targets: nvgpu_kzalloc_impl, nvgpu_kfree_impl
*
* Inputs:
* 1) GPU driver struct g.
* 2) Global define for size to alloc.
*
* Steps:
* 1) Call nvgpu_kzalloc_impl with size as a parameter.
* 2) Check the return value from nvgpu_kmalloc_impl function. If the return
* value is NULL, return test FAIL.
* 3) Check if the allocated chunk of memory is zero initialized. If it is not,
* free the memory and return FAIL.
* 3) Free the allocated memory.
* 4) Return PASS.
*
* Output:
* The test returns PASS if the zero initialized memory is successfully
* allocated. Otherwise, the test returns FAIL.
*/
int test_kmem_kzalloc(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_kmem_kcalloc
*
* Description: Test the allocation of memory using kcalloc.
*
* Test Type: Feature
*
* Targets: nvgpu_kcalloc_impl, nvgpu_kfree_impl
*
* Inputs:
* 1) GPU driver struct g.
* 2) Global define for size to alloc.
* 3) Global define for count to alloc.
*
* Steps:
* 1) Call nvgpu_kcalloc_impl with size and count as parameters.
* 2) Check the return value from nvgpu_kmalloc_impl function. If the return
* value is NULL, return test FAIL.
* 3) Check if the allocated chunk of memory is zero initialized. If it is not,
* free the memory and return FAIL.
* 3) Free the allocated memory.
* 4) Return PASS.
*
* Output:
* The test returns PASS if the zero initialized memory is successfully
* allocated. Otherwise, the test returns FAIL.
*/
int test_kmem_kcalloc(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_kmem_virtual_alloc
*
* Description: Test the allocation of memory using virtual alloc APIs.
*
* Test Type: Feature
*
* Targets: nvgpu_vmalloc_impl, nvgpu_vfree_impl,
* nvgpu_vzalloc_impl
*
* Inputs:
* 1) GPU driver struct g.
* 2) Global define for cache size to alloc.
*
* Steps:
* 1) Call nvgpu_vmalloc_impl with size as a parameter.
* 2) Check the return value from nvgpu_vmalloc_impl function. If the return
* value is NULL, return test FAIL.
* 3) Free the memory using nvgpu_vfree_impl.
* 4) Call nvgpu_vzalloc_impl with size as a parameter.
* 5) Check the return value from nvgpu_vzalloc_impl function. If the return
* value is NULL, return test FAIL.
* 6) Check if the allocated chunk of memory is zero initialized. If it is not,
* free the memory and return FAIL.
* 7) Free the memory using nvgpu_vfree_impl.
* 8) Return PASS.
*
* Output:
* The test returns PASS if,
* - The virtual allocation API nvgpu_vmalloc_impl successfully allocates memory.
* - The virtual allocation API nvgpu_vzalloc_impl successfully allocates zero
* initialised memory.
* If any of the above points fail, the test returns FAIL.
*/
int test_kmem_virtual_alloc(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_kmem_big_alloc
*
* Description: Test the allocation of memory using big alloc APIs.
*
* Test Type: Feature
*
* Targets: nvgpu_big_alloc_impl, nvgpu_big_free
*
* Inputs:
* 1) GPU driver struct g.
* 2) Global define for cache size to alloc.
*
* Steps:
* 1) Call nvgpu_big_alloc_impl with size as a parameter and clear flag set to
* false.
* 2) Check the return value from nvgpu_big_alloc_impl function. If the return
* value is NULL, return test FAIL.
* 3) Free the memory using nvgpu_big_free.
* 4) Call nvgpu_big_alloc_impl with size as a parameter and clear flag set to
* true.
* 5) Check the return value from nvgpu_big_alloc_impl function. If the return
* value is NULL, return test FAIL.
* 6) Check if the allocated chunk of memory is zero initialized. If it is not,
* free the memory and return FAIL.
* 7) Free the memory using nvgpu_big_free..
* 8) Return PASS.
*
* Output:
*
*/
int test_kmem_big_alloc(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_KMEM_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 = posix-log2.o
MODULE = posix-log2
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-log2
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) 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-log2
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,169 @@
/*
* 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 <unistd.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/log2.h>
#include "posix-log2.h"
int test_ilog2(struct unit_module *m,
struct gk20a *g, void *args)
{
unsigned long i, test, ret;
for (i = 0; i < BITS_PER_LONG; i++) {
test = 1UL << i;
ret = ilog2(test);
if (ret != i) {
unit_return_fail(m,
"ilog2 failure %ld\n", test);
}
}
for (i = 1; i < (BITS_PER_LONG - 1); i++) {
test = 1UL << i;
test += 1;
ret = ilog2(test);
if (ret != i) {
unit_return_fail(m,
"ilog2 failure %ld\n", test);
}
}
return UNIT_SUCCESS;
}
int test_roundup_powoftwo(struct unit_module *m,
struct gk20a *g, void *args)
{
unsigned long i, test, ret;
test = 0UL;
if (!EXPECT_BUG(roundup_pow_of_two(test))) {
unit_return_fail(m,
"roundup_pow_of_two did not invoke BUG()\n");
} else {
unit_info(m, "BUG invoked as expected for input value 0\n");
}
for (i = 0; i < BITS_PER_LONG; i++) {
test = 1UL << i;
ret = roundup_pow_of_two(test);
if (ret != test) {
unit_return_fail(m,
"roundup_pow_of_two failure.\n");
}
}
for (i = 0; i < (BITS_PER_LONG - 1); i++) {
test = 1UL << i;
test += 1;
ret = roundup_pow_of_two(test);
if (ret != (1UL << (i + 1))) {
unit_return_fail(m,
"roundup_pow_of_two failure.\n");
}
}
return UNIT_SUCCESS;
}
int test_rounddown_powoftwo(struct unit_module *m,
struct gk20a *g, void *args)
{
unsigned long i, test, ret;
test = 0UL;
if (!EXPECT_BUG(rounddown_pow_of_two(test))) {
unit_return_fail(m,
"rounddown_pow_of_two did not invoke BUG()\n");
} else {
unit_info(m, "BUG invoked as expected for input value 0\n");
}
for (i = 0; i < BITS_PER_LONG; i++) {
test = 1UL << i;
ret = rounddown_pow_of_two(test);
if (ret != test) {
unit_return_fail(m,
"rounddown_pow_of_two failure.\n");
}
}
for (i = 1; i < BITS_PER_LONG; i++) {
test = 1UL << i;
test -= 1;
ret = rounddown_pow_of_two(test);
if (ret != (1UL << (i - 1))) {
unit_return_fail(m,
"rounddown_pow_of_two failure.\n");
}
}
return UNIT_SUCCESS;
}
int test_ispow2(struct unit_module *m,
struct gk20a *g, void *args)
{
bool ret;
unsigned long i, test;
test = 0UL;
for (i = 0; i < BITS_PER_LONG; i++) {
test = 1UL << i;
ret = is_power_of_2(test);
if (!ret) {
unit_return_fail(m,
"is_power_of_2 failure %ld\n", test);
}
}
for (i = 1; i < (BITS_PER_LONG - 1); i++) {
test = 1UL << i;
test += 1;
ret = is_power_of_2(test);
if (ret) {
unit_return_fail(m,
"is_power_of_2 failure %ld\n", test);
}
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_log2_tests[] = {
UNIT_TEST(integer_log2, test_ilog2, NULL, 0),
UNIT_TEST(roundup_pow2, test_roundup_powoftwo, NULL, 0),
UNIT_TEST(rounddown_pow2, test_rounddown_powoftwo, NULL, 0),
UNIT_TEST(is_powof2, test_ispow2, NULL, 0),
};
UNIT_MODULE(posix_log2, posix_log2_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,147 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-log2
* @{
*
* Software Unit Test Specification for posix-log2
*/
#ifndef UNIT_POSIX_LOG2_H
#define UNIT_POSIX_LOG2_H
/**
* Test specification for test_ilog2
*
* Description: Test integer logarithm of base 2 implementation.
*
* Test Type: Feature
*
* Targets: ilog2
*
* Inputs: None
*
* Steps:
* 1) Invoke ilog2 in loop for all the power of two numbers that can be held in
* an unsigned long variable.
* 2) Confirm if the return value from the macro is equal to the loop index.
* 3) Return false otherwise.
* 4) Invoke ilog2 in loop for numbers which are one greater than the power of
* two.
* 5) Confirm if the return value from the macro is equal to the loop index.
* 6) Return false otherwise.
*
* Output:
* The test returns PASS if all the invocations of ilog2 returns the log to
* the base 2 of the input number as expected. Otherwise, test returns FAIL.
*/
int test_ilog2(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_roundup_powoftwo
*
* Description: Test round up power of two implementation.
*
* Test Type: Feature
*
* Targets: roundup_pow_of_two
*
* Inputs: None
*
* Steps:
* 1) Invoke roundup_pow_of_two for input value 0UL using EXPECT_BUG.
* 2) Check if EXPECT_BUG returns true, otherwise, return fail.
* 3) Invoke roundup_pow_of_two in loop for all the power of two numbers
* that can be held in an unsigned long variable.
* 4) Confirm if the return value from the macro is equal to the input argument
* passed. Return false otherwise.
* 5) Invoke roundup_pow_of_two in loop for numbers which are one greater than
* the power of two.
* 6) Confirm if the return value from the macro is equal to the rounded up
* power of two value of the input number. Return false otherwise.
*
* Output:
* The test returns PASS if all the invocations of roundup_pow_of_two
* returns the expected value as result. Otherwise, test returns FAIL.
*/
int test_roundup_powoftwo(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_rounddown_powoftwo
*
* Description: Test round down power of two implementation.
*
* Test Type: Feature
*
* Targets: rounddown_pow_of_two
*
* Inputs: None
*
* Steps:
* 1) Invoke rounddown_pow_of_two for input value 0UL using EXPECT_BUG.
* 2) Check if EXPECT_BUG returns true, otherwise, return fail.
* 3) Invoke rounddown_pow_of_two in loop for all the power of two numbers
* that can be held in an unsigned long variable.
* 4) Confirm if the return value from the macro is equal to the input argument
* passed. Return false otherwise.
* 5) Invoke rounddown_pow_of_two in loop for numbers which are one less than
* the power of two.
* 6) Confirm if the return value from the macro is equal to the power of two
* rounded down value of the input number. Return false otherwise.
*
* Output:
* The test returns PASS if all the invocations of rounddown_pow_of_two
* returns the expected value as result. Otherwise, test returns FAIL.
*/
int test_rounddown_powoftwo(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_ispow2
*
* Description: Test the power of two implementation.
*
* Test Type: Feature
*
* Targets: is_power_of_2
*
* Inputs: None
*
* Steps:
* 1) Invoke is_power_of_2 in loop for all the power of two numbers that can
* be held in an unsigned long variable.
* 2) Confirm if the return value from the macro is true, else, return fail.
* 3) Invoke is_power_of_2 in loop for numbers which are one greater than the
* power of two.
* 4) Confirm if the return value from the macro is false. Otherwise, return
* fail.
*
* Output:
* The test returns PASS if all the invocations of is_power_of_2 returns the
* result as expected. Otherwise, test returns FAIL.
*/
int test_ispow2(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* UNIT_POSIX_LOG2_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 = posix-ossched.o
MODULE = posix-ossched
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=posix-ossched
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) 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=posix-ossched
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,81 @@
/*
* 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 <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <unit/io.h>
#include <unit/unit.h>
#include "posix-ossched.h"
int test_current_pid(struct unit_module *m,
struct gk20a *g, void *args)
{
int pid;
int nvgpu_pid;
pid = (int) getpid();
nvgpu_pid = nvgpu_current_pid(g);
if (nvgpu_pid != pid) {
unit_return_fail(m, "PID mismatch %d %d\n", pid, nvgpu_pid);
}
return UNIT_SUCCESS;
}
int test_current_tid(struct unit_module *m,
struct gk20a *g, void *args)
{
int tid;
int nvgpu_tid;
tid = (int) pthread_self();
nvgpu_tid = nvgpu_current_tid(g);
if (nvgpu_tid != tid) {
unit_return_fail(m, "TID mismatch %d %d\n", tid, nvgpu_tid);
}
return UNIT_SUCCESS;
}
int test_print_current(struct unit_module *m,
struct gk20a *g, void *args)
{
nvgpu_print_current(g, NULL, NVGPU_INFO);
nvgpu_print_current(g, NULL, NVGPU_DEBUG);
nvgpu_print_current(g, NULL, NVGPU_WARNING);
nvgpu_print_current(g, NULL, NVGPU_ERROR);
nvgpu_print_current(g, NULL, 10);
return UNIT_SUCCESS;
}
struct unit_module_test posix_ossched_tests[] = {
UNIT_TEST(current_pid, test_current_pid, NULL, 0),
UNIT_TEST(current_tid, test_current_tid, NULL, 0),
UNIT_TEST(print_current, test_print_current, NULL, 0),
};
UNIT_MODULE(posix_ossched, posix_ossched_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,109 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-ossched
* @{
*
* Software Unit Test Specification for posix-ossched
*/
#ifndef __UNIT_POSIX_OSSCHED_H__
#define __UNIT_POSIX_OSSCHED_H__
#include <nvgpu/os_sched.h>
/**
* Test specification for test_current_pid
*
* Description: Test the PID of the current process.
*
* Test Type: Feature
*
* Targets: nvgpu_current_pid
*
* Inputs:
*
* Steps:
* 1) Get the PID of the current process using standard lib call.
* 2) Get the PID of the current process using NVGPU API.
* 3) Compare the PIDs obtained in step 1 and 2.
* 4) Return Fail if the PIDs dont match.
*
* Output:
* Return PASS if the PIDs fetched using standard library call and NVGPU API
* matches; otherwise, the test returns FAIL.
*/
int test_current_pid(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_current_tid
*
* Description: Test the TID of the current thread.
*
* Test Type: Feature
*
* Targets: nvgpu_current_tid
*
* Inputs:
*
* Steps:
* 1) Get the TID of the current thread using standard lib call.
* 2) Get the TID of the current thread using NVGPU API.
* 3) Compare the TIDs obtained in step 1 and 2.
* 4) Return Fail if the TIDs dont match.
*
* Output:
* Return PASS if the TIDs fetched using standard library call and NVGPU API
* matches; otherwise, the test returns FAIL.
*/
int test_current_tid(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_print_current
*
* Description: Print the current thread name.
*
* Test Type: Feature
*
* Targets: nvgpu_print_current, nvgpu_print_current_impl
*
* Inputs:
*
* Steps:
* 1) Print the current thread name with log type NVGPU_INFO
* 2) Print the current thread name with log type NVGPU_DEBUG
* 3) Print the current thread name with log type NVGPU_WARNING
* 4) Print the current thread name with log type NVGPU_ERROR
* 5) Print the current thread name with invalid log type which should result
* in the function using default log type.
*
* Output:
* The test returns PASS if all the print calls gets executed without any
* crash/hang. Since the function does not return any value, the only case
* in which the test can fail is due to an internal hang or crash.
*/
int test_print_current(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_OSSCHED_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 = posix-queue.o
MODULE = posix-queue
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-queue
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) 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-queue
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,284 @@
/*
* 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 <unistd.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/types.h>
#include <nvgpu/posix/queue.h>
#include <nvgpu/posix/kmem.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include "posix-queue.h"
#define QUEUE_LEN 10
#define QUEUE_LEN_POW_2 16
#define BUF_LEN 10
int test_nvgpu_queue_alloc_and_free(struct unit_module *m, struct gk20a *g,
void *args)
{
int ret = 0, err = UNIT_SUCCESS;
struct nvgpu_queue q = {0};
struct nvgpu_posix_fault_inj *kmem_fi =
nvgpu_kmem_get_fault_injection();
ret = nvgpu_queue_alloc(NULL, QUEUE_LEN);
if (ret != -EINVAL) {
err = UNIT_FAIL;
unit_err(m, "%d. test_queue_alloc failed err=%d\n", __LINE__,
ret);
goto fail;
}
ret = nvgpu_queue_alloc(&q, 0);
if (ret != -EINVAL) {
err = UNIT_FAIL;
unit_err(m, "%d. test_queue_alloc failed err=%d\n", __LINE__,
ret);
goto fail;
}
ret = nvgpu_queue_alloc(&q, (unsigned int)INT64_MAX);
if (ret != -EINVAL) {
err = UNIT_FAIL;
unit_err(m, "%d. test_queue_alloc failed err=%d\n", __LINE__,
ret);
goto fail;
}
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
ret = nvgpu_queue_alloc(&q, QUEUE_LEN_POW_2);
if (ret != -ENOMEM) {
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
err = UNIT_FAIL;
unit_err(m, "%d. test_queue_alloc failed err=%d\n", __LINE__,
ret);
goto fail;
}
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
ret = nvgpu_queue_alloc(&q, QUEUE_LEN);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. test_queue_alloc failed err=%d\n", __LINE__,
ret);
goto fail;
}
nvgpu_queue_free(&q);
ret = nvgpu_queue_alloc(&q, QUEUE_LEN_POW_2);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. test_queue_alloc failed err=%d\n", __LINE__,
ret);
goto fail;
}
nvgpu_queue_free(&q);
fail:
return err;
}
int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = 0, err = UNIT_SUCCESS;
struct nvgpu_queue q = {0};
struct nvgpu_mutex lock;
char buf[BUF_LEN];
nvgpu_mutex_init(&lock);
/* Allocate Queue of size QUEUE_LEN_POW_2 */
ret = nvgpu_queue_alloc(&q, QUEUE_LEN_POW_2);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_alloc failed err=%d\n", __LINE__, ret);
goto fail;
}
/* Enqueue message of length BUF_LEN */
ret = nvgpu_queue_in(&q, buf, BUF_LEN);
if (ret != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail;
}
/*
* Update "in" and "out" indexes and enqueue message of length BUF_LEN
* such that we wrap around the Queue while enqueuing the message.
*/
q.in = BUF_LEN;
q.out = BUF_LEN;
ret = nvgpu_queue_in(&q, buf, BUF_LEN);
if (ret != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail;
}
/*
* Reset "in" and "out" indexes and enqueue message of length BUF_LEN
* with the lock.
*/
q.in = 0;
q.out = 0;
ret = nvgpu_queue_in_locked(&q, buf, BUF_LEN, &lock);
if (ret != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail;
}
/* Enqueue message of length BUF_LEN again and expect memory full */
ret = nvgpu_queue_in_locked(&q, buf, BUF_LEN, &lock);
if (ret != -ENOMEM) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail;
}
/* Enqueue message of length BUF_LEN again (without lock) and expect
* memory full.
*/
ret = nvgpu_queue_in(&q, buf, BUF_LEN);
if (ret != -ENOMEM) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_in failed err=%d\n", __LINE__, ret);
goto fail;
}
fail:
if (q.data != NULL)
free(q.data);
nvgpu_mutex_destroy(&lock);
return err;
}
int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = 0, err = UNIT_SUCCESS;
struct nvgpu_queue q = {0};
struct nvgpu_mutex lock;
char buf[BUF_LEN];
struct nvgpu_posix_fault_inj *queue_out_fi =
nvgpu_queue_out_get_fault_injection();
nvgpu_mutex_init(&lock);
/* Allocate Queue of size QUEUE_LEN_POW_2 */
ret = nvgpu_queue_alloc(&q, QUEUE_LEN_POW_2);
if (ret != 0) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_alloc failed err=%d\n", __LINE__, ret);
goto fail;
}
/* Queue is empty. Dequeue message should return "-ENOMEM" */
ret = nvgpu_queue_out(&q, buf, BUF_LEN);
if (ret != -ENOMEM) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail;
}
/* Queue is empty. Dequeue message with lock should return "-ENOMEM" */
ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock);
if (ret != -ENOMEM) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail;
}
/*
* Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN
*/
q.in = BUF_LEN;
q.out = 0;
ret = nvgpu_queue_out(&q, buf, BUF_LEN);
if (ret != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail;
}
/*
* Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN
* with the lock.
*/
q.in = BUF_LEN;
q.out = 0;
ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock);
if (ret != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail;
}
/*
* Update "in" and "out" indexes and dequeue message of length BUF_LEN
* such that we wrap around the Queue while dequeuing the message.
*/
q.in = 1;
q.out = QUEUE_LEN_POW_2 -(BUF_LEN -1);
ret = nvgpu_queue_out(&q, buf, BUF_LEN);
if (ret != BUF_LEN) {
err = UNIT_FAIL;
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail;
}
/*
* Fault injection so that immediate call to nvgpu_queue_out_locked()
* API would return error.
*/
nvgpu_posix_enable_fault_injection(queue_out_fi, true, 0);
ret = nvgpu_queue_out_locked(&q, buf, BUF_LEN, &lock);
if (ret != -1) {
err = UNIT_FAIL;
nvgpu_posix_enable_fault_injection(queue_out_fi, false, 0);
unit_err(m, "%d. queue_out failed err=%d\n", __LINE__, ret);
goto fail;
}
nvgpu_posix_enable_fault_injection(queue_out_fi, false, 0);
fail:
if (q.data != NULL)
free(q.data);
nvgpu_mutex_destroy(&lock);
return err;
}
struct unit_module_test posix_queue_tests[] = {
UNIT_TEST(nvgpu_queue_alloc_free, test_nvgpu_queue_alloc_and_free,
NULL, 0),
UNIT_TEST(nvgpu_queue_in, test_nvgpu_queue_in, NULL, 0),
UNIT_TEST(nvgpu_queue_out, test_nvgpu_queue_out, NULL, 0),
};
UNIT_MODULE(posix_queue, posix_queue_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,154 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-queue
* @{
*
* Software Unit Test Specification for posix-queue
*/
#ifndef __UNIT_POSIX_QUEUE_H__
#define __UNIT_POSIX_QUEUE_H__
/**
* Test specification for: test_nvgpu_queue_alloc_and_free
*
* Description: Functionalities of posix queue such as allocating and freeing
* of the message queue are tested.
*
* Test Type: Feature, Error guessing, Boundary values
*
* Targets: nvgpu_queue_alloc, nvgpu_queue_free
*
* Input: None
*
* Steps:
* - Pass NULL nvgpu_queue pointer as argument to nvgpu_queue_alloc() API and
* check that the API returns "-EINVAL" error.
* - Pass zero size queue length as argument to nvgpu_queue_alloc() API and
* check that the API returns "-EINVAL" error.
* - Pass "INT64_MAX" size queue length as argument to nvgpu_queue_alloc() API
* and check that the API returns "-EINVAL" error.
* - Inject fault so that immediate call to nvgpu_kzalloc() API would fail.
* - Check that when the nvgpu_queue_alloc() API is called with valid arguments,
* it would fail by returning "-ENOMEM" error.
* - Remove the injected fault in nvgpu_kzalloc() API.
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success.
* - Valid pointer to "struct nvgpu_queue"
* - Queue size which is not power of 2
* - Free the allocated queue by caling nvgpu_queue_free() API.
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success.
* - Valid pointer to "struct nvgpu_queue"
* - Queue size which is power of 2
* - Free the allocated queue by caling nvgpu_queue_free() API.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_queue_alloc_and_free(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: test_nvgpu_queue_in
*
* Description: Functionalities of posix queue such as allocating queue and
* enqueueing messages into the queue are tested.
*
* Test Type: Feature, Error guessing, Boundary values
*
* Targets: nvgpu_queue_alloc, nvgpu_queue_in, nvgpu_queue_in_locked,
* nvgpu_queue_unused, nvgpu_queue_available
*
* Input: None
*
* Steps:
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success.
* - Valid pointer to "struct nvgpu_queue"
* - Queue size which is power of 2
* - Enqueue message of length "BUF_LEN" calling nvgpu_queue_in() API and check
* that the API returns "BUF_LEN".
* - Update "in" and "out" indexes and enqueue message of length BUF_LEN such
* that we wrap around the Queue while enqueuing the message using
* nvgpu_queue_in() API. Check that the API returns "BUF_LEN".
* - Reset "in" and "out" indexes and enqueue message of length "BUF_LEN" with
* the lock using nvgpu_queue_in_locked() API. Check that the API returns
* "BUF_LEN".
* - Enqueue message of length "BUF_LEN" again using nvgpu_queue_in_locked()
* API. Check that the API returns error "-ENOMEM".
* - Enqueue message of length "BUF_LEN" again using nvgpu_queue_in() API. Check
* that the API returns error "-ENOMEM".
* - Uninitialize the allocated resources.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_queue_in(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_queue_out
*
* Description: Functionalities of posix queue such as allocating queue and
* dequeuing messages from the queue are tested.
*
* Test Type: Feature, Error guessing, Boundary values
*
* Targets: nvgpu_queue_alloc, nvgpu_queue_out, nvgpu_queue_out_locked
*
* Input: None
*
* Steps:
* - Pass below valid arguments to nvgpu_queue_alloc() API and check that the
* API returns success.
* - Valid pointer to "struct nvgpu_queue"
* - Queue size which is power of 2
* - Dequeue message of length "BUF_LEN" from the empty queue calling
* nvgpu_queue_out() API and check that the API returns "-ENOMEM" error.
* - Dequeue message of length "BUF_LEN" from the empty queue calling
* nvgpu_queue_out_locked() API and check that the API returns "-ENOMEM"
* error.
* - Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN by
* calling nvgpu_queue_out() API and check that the API returns "BUF_LEN".
* - Advance "in" index by "BUF_LEN" and dequeue message of length BUF_LEN by
* calling nvgpu_queue_out_locked() API and check that the API returns
* "BUF_LEN".
* - Update "in" and "out" indexes and dequeue message of length BUF_LEN such
* that we wrap around the Queue while dequeuing the message using
* nvgpu_queue_out() API. Check that the API returns "BUF_LEN".
* - Do fault injection so that immediate call to nvgpu_queue_out_locked() API
* would return error.
* - Invoke nvgpu_queue_out_locked() API and check that API returns -1 error.
* - Remove the injected fault.
* - Uninitialize the allocated resources.
*
* Output: Returns PASS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_queue_out(struct unit_module *m, struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_QUEUE_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 = posix-rwsem.o
MODULE = posix-rwsem
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=posix-rwsem
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) 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=posix-rwsem
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, 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 <unistd.h>
#include <string.h>
#include <pthread.h>
#include <unit/io.h>
#include <unit/unit.h>
#include "posix-rwsem.h"
struct unit_test_rwsem_data {
unsigned int read_pattern;
unsigned int write_pattern;
bool read1_locked;
bool read2_locked;
bool write1_locked;
bool write2_locked;
bool wrlock_err;
bool wrpattern_err;
bool write_read_test;
bool read_lock_fail;
};
static struct unit_test_rwsem_data test_data;
static struct nvgpu_rwsem test_rwsem;
static void *test_rwsem_read1_thread(void *args)
{
int ret;
struct unit_test_rwsem_data *data;
data = (struct unit_test_rwsem_data *)args;
if (data->write_read_test == true) {
while (data->write1_locked == false) {
usleep(1);
}
ret = pthread_rwlock_tryrdlock(&test_rwsem.rw_sem);
if (ret != 0) {
data->read_lock_fail = true;
usleep(2);
}
}
nvgpu_rwsem_down_read(&test_rwsem);
data->read1_locked = true;
while (data->read2_locked == false) {
if (data->write1_locked) {
if (data->write_pattern != 0xCCCCCCCC) {
data->wrpattern_err = true;
}
break;
}
usleep(1);
}
nvgpu_rwsem_up_read(&test_rwsem);
return NULL;
}
static void *test_rwsem_read2_thread(void *args)
{
struct unit_test_rwsem_data *data;
data = (struct unit_test_rwsem_data *)args;
while (data->read1_locked == false) {
usleep(1);
}
nvgpu_rwsem_down_read(&test_rwsem);
data->read2_locked = true;
nvgpu_rwsem_up_read(&test_rwsem);
return NULL;
}
static void *test_rwsem_write1_thread(void *args)
{
struct unit_test_rwsem_data *data;
data = (struct unit_test_rwsem_data *)args;
nvgpu_rwsem_down_write(&test_rwsem);
data->write_pattern = 0xCCCCCCCC;
data->write1_locked = true;
usleep(5);
if (data->write_read_test == true) {
while (data->read_lock_fail == false) {
usleep(1);
}
}
if ((data->write2_locked == true) || (data->read1_locked == true)) {
data->wrlock_err = true;
}
nvgpu_rwsem_up_write(&test_rwsem);
return NULL;
}
static void *test_rwsem_write2_thread(void *args)
{
struct unit_test_rwsem_data *data;
data = (struct unit_test_rwsem_data *)args;
while (data->write1_locked == false) {
usleep(1);
}
nvgpu_rwsem_down_write(&test_rwsem);
data->write2_locked = true;
if (data->write_pattern != 0xCCCCCCCC) {
data->wrpattern_err = true;
}
data->write_pattern = 0xDDDDDDDD;
nvgpu_rwsem_up_write(&test_rwsem);
return NULL;
}
int test_rwsem_init(struct unit_module *m, struct gk20a *g, void *args)
{
nvgpu_rwsem_init(&test_rwsem);
usleep(1);
pthread_rwlock_destroy(&test_rwsem.rw_sem);
return UNIT_SUCCESS;
}
int test_rwsem_read(struct unit_module *m, struct gk20a *g, void *args)
{
int ret;
pthread_t thread_read1, thread_read2;
(void) memset(&test_data, 0, sizeof(struct unit_test_rwsem_data));
nvgpu_rwsem_init(&test_rwsem);
ret = pthread_create(&thread_read1, NULL,
&test_rwsem_read1_thread, &test_data);
if (ret != 0) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Read1 thread creation failed\n");
}
ret = pthread_create(&thread_read2, NULL,
&test_rwsem_read2_thread, &test_data);
if (ret != 0) {
pthread_cancel(thread_read1);
pthread_join(thread_read1, NULL);
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Read2 thread creation failed\n");
}
pthread_join(thread_read1, NULL);
pthread_join(thread_read2, NULL);
pthread_rwlock_destroy(&test_rwsem.rw_sem);
return UNIT_SUCCESS;
}
int test_rwsem_write(struct unit_module *m, struct gk20a *g, void *args)
{
int ret;
pthread_t thread_write1, thread_write2;
(void) memset(&test_data, 0, sizeof(struct unit_test_rwsem_data));
nvgpu_rwsem_init(&test_rwsem);
test_data.write_pattern = 0xABABABAB;
ret = pthread_create(&thread_write1, NULL,
&test_rwsem_write1_thread, &test_data);
if (ret != 0) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Write1 thread creation failed\n");
}
ret = pthread_create(&thread_write2, NULL,
&test_rwsem_write2_thread, &test_data);
if (ret != 0) {
pthread_cancel(thread_write1);
pthread_join(thread_write1, NULL);
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Write2 thread creation failed\n");
}
pthread_join(thread_write1, NULL);
pthread_join(thread_write2, NULL);
if (test_data.wrpattern_err == true) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Write pattern from write1 mismatch\n");
} else if (test_data.wrlock_err == true) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Lock error observed by write1 thread\n");
} else if (test_data.write_pattern != 0xDDDDDDDD) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Write pattern from write2 mismatch\n");
}
pthread_rwlock_destroy(&test_rwsem.rw_sem);
return UNIT_SUCCESS;
}
int test_rwsem_write_read(struct unit_module *m, struct gk20a *g, void *args)
{
int ret;
pthread_t thread_write, thread_read;
(void) memset(&test_data, 0, sizeof(struct unit_test_rwsem_data));
nvgpu_rwsem_init(&test_rwsem);
test_data.write_pattern = 0xABABABAB;
test_data.write_read_test = true;
ret = pthread_create(&thread_write, NULL,
&test_rwsem_write1_thread, &test_data);
if (ret != 0) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Write thread creation failed\n");
}
ret = pthread_create(&thread_read, NULL,
&test_rwsem_read1_thread, &test_data);
if (ret != 0) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
pthread_cancel(thread_write);
pthread_join(thread_write, NULL);
unit_return_fail(m, "Read thread creation failed\n");
}
pthread_join(thread_write, NULL);
pthread_join(thread_read, NULL);
if (test_data.wrpattern_err == true) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Write pattern mismatch\n");
} else if (test_data.wrlock_err == true) {
pthread_rwlock_destroy(&test_rwsem.rw_sem);
unit_return_fail(m, "Lock error observed by write thread\n");
}
pthread_rwlock_destroy(&test_rwsem.rw_sem);
return UNIT_SUCCESS;
}
struct unit_module_test posix_rwsem_tests[] = {
UNIT_TEST(init, test_rwsem_init, NULL, 0),
UNIT_TEST(read, test_rwsem_read, NULL, 0),
UNIT_TEST(write, test_rwsem_write, NULL, 0),
UNIT_TEST(write_read, test_rwsem_write_read, NULL, 0),
};
UNIT_MODULE(posix_rwsem, posix_rwsem_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,233 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-rwsem
* @{
*
* Software Unit Test Specification for posix-rwsem
*/
#ifndef __UNIT_POSIX_RWSEM_H__
#define __UNIT_POSIX_RWSEM_H__
#include <nvgpu/rwsem.h>
/**
* Test specification for test_rwsem_init.
*
* Description: Initialisation of rwsem.
*
* Test Type: Feature
*
* Targets: nvgpu_rwsem_init
*
* Inputs:
* 1) Global nvgpu_rwsem instance.
*
* Steps:
* 1) Call nvgpu API to initialise the rwsem.
* 2) Sleep for some time and destroy the rwsem.
* 3) Return success.
*
* Output:
* Returns success if the rwsem is initialised.
*
*/
int test_rwsem_init(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_rwsem_read.
*
* Description: Testing the locking of a rwlock by multiple read threads.
*
* Test Type: Feature
*
* Targets: nvgpu_rwsem_init, nvgpu_rwsem_down_read,
* nvgpu_rwsem_up_read
*
* Inputs:
* 1) Global nvgpu_rwsem instance.
* 2) Global test_data instance.
*
* Steps:
* There are three threads involved in this test, a main thread which creates
* multiple reader threads and waits for the reader threads to return.
*
* Main thread
* 1) Initialize the global nvgpu_rwsem instance.
* 2) Create a thread for first reader.
* 3) Check for the return status of thread creation. If thread creation
* fails, destroy the rwsem instance and return failure.
* 4) Create a thread for second reader.
* 5) Check for the return status of thread creation. If thread creation
* fails, cancel the first reader thread, destroy the rwsem and return
* failure.
* 6) Use pthread_join to wait for both the reader threads to return.
* 7) Destroy the rwsem and return success.
*
* Reader Thread 1
* 1) Acquires the read lock on rwsem.
* 2) Set the flag read1_locked as true.
* 3) Wait on read2_locked flag till it is true.
* 4) Release the rwsem once read2_locked is true.
* 5) Return from the thread handler.
*
* Reader thread 2
* 1) Wait on read1_locked to be true, this ensures that the first reader
* thread has acquired the read lock.
* 2) Acquire the read lock on rwsem.
* 3) Set read2_locked as true.
* 4) Release the rwsem.
* 5) Return from the thread handler.
*
* Output:
* Returns success if both the threads are able to acquire read locks.
* If any of the thread hangs without acquiring the lock, the test should fail
* after the global timeout.
*
*/
int test_rwsem_read(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_rwsem_write.
*
* Description: Testing the locking of a rwlock by multiple write threads.
*
* Test Type: Feature
*
* Targets: nvgpu_rwsem_init, nvgpu_rwsem_down_write,
* nvgpu_rwsem_up_write
*
* Inputs:
* 1) Global nvgpu_rwsem instance.
* 2) Global test_data instance.
*
* Steps:
* There are three threads involved in this test, a main thread which
* creates multiple write threads and waits for the write threads to return.
*
* Main thread
* 1) Initialize the global test_data structure.
* 2) Initialize the global nvgpu_rwsem instance.
* 3) Update the write pattern in test_data structure.
* 4) Create a thread for first writer.
* 5) Check for the return status of thread creation. If thread creation
* fails, destroy the rwsem instance and return failure.
* 6) Create a thread for second writer.
* 7) Check for the return status of thread creation. If thread creation
* fails, cancel the first thread, destroy the rwsem and return
* failure.
* 6) Use pthread_join to wait for both the reader threads to return.
* 7) Check if the write pattern in test_data matches with the data written
* by second thread. Return FAIL if it doesn't match.
* 8) Destroy the rwsem and return success.
*
* Writer Thread 1
* 1) Acquires the write lock on rwsem.
* 2) Set the flag write1_locked as true.
* 3) Delay the execution using sleep to let the second write thread try
* acquire the lock.
* 4) Update the write pattern.
* 5) Check if second write thread status indicates an acquired write lock,
* and populate error status if so.
* 4) Release the rwsem.
* 5) Return from the thread handler.
*
* Writer thread 2
* 1) Wait on write1_locked to be true, this ensures that the first writer
* thread has acquired the write lock.
* 2) Try to acquire the write lock on rwsem, this should put the thread in
* inactive state waiting for the lock to be available.
* 3) Set write2_locked as true once the thread is woken up.
* 4) Check for the write pattern if it matches with what thread 1 has written.
* 5) Update the write pattern.
* 4) Release the rwsem.
* 5) Return from the thread handler.
*
* Output:
* Return success if the second write thread is able to lock rwsem only after
* the first write thread releases it, else return failure.
*/
int test_rwsem_write(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_rwsem_write_read.
*
* Description: Testing the locking of a rwlock by write and read threads.
*
* Test Type: Feature
*
* Inputs:
* 1) Global nvgpu_rwsem instance.
* 2) Global test_data instance.
*
* Steps:
* There are three threads involved in this test, a main thread which
* creates a write thread and a read thread and waits for the threads to
* return.
*
* Main thread
* 1) Initialize the global test_data structure.
* 2) Initialize the global nvgpu_rwsem instance.
* 3) Update the write pattern in test_data structure.
* 4) Create a thread for writer.
* 5) Check for the return status of thread creation. If thread creation
* fails, destroy the rwsem instance and return failure.
* 6) Create a thread for reader.
* 7) Check for the return status of thread creation. If thread creation
* fails, cancel the first thread, destroy the rwsem and return
* failure.
* 6) Use pthread_join to wait for both the reader threads to return.
* 7) Destroy the rwsem and return success.
*
* Writer Thread
* 1) Acquires the write lock on rwsem.
* 2) Set the flag write1_locked as true.
* 3) Delay the execution using sleep to let the second thread try
* acquire the lock.
* 4) Update the write pattern.
* 5) Check if second thread status indicates an acquired lock,
* and populate error status if so.
* 4) Release the rwsem.
* 5) Return from the thread handler.
*
* Reader thread
* 1) Try to acquire the lock on rwsem, this should put the thread in
* inactive state waiting for the lock to be available.
* 2) Set read1_locked as true once the thread is woken up.
* 3) Check for the write pattern if it matches with what thread 1 has written.
* Update error status if the pattern does not match.
* 4) Release the rwsem.
* 5) Return from the thread handler.
*
*
* Output:
* Returns success if the read thread is able to lock rwsem only after
* write thread releases it, else returns failure.
*
*/
int test_rwsem_write_read(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_RWSEM_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 = posix-sizes.o
MODULE = posix-sizes
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=posix-sizes
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=posix-sizes
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,96 @@
/*
* 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 "posix-sizes.h"
int test_size_defines(struct unit_module *m, struct gk20a *g, void *args)
{
unsigned long long size = 0;
size = 256;
if (size != SZ_256) {
unit_return_fail(m, "Size 256 Mismatch : %ld\n", SZ_256);
}
size = 1024;
if (size != SZ_1K) {
unit_return_fail(m, "Size 1K Mismatch : %ld\n", SZ_1K);
}
size = (4 * 1024);
if (size != SZ_4K) {
unit_return_fail(m, "Size 4K Mismatch : %ld\n", SZ_4K);
}
size = (64 * 1024);
if (size != SZ_64K) {
unit_return_fail(m, "Size 64K Mismatch : %ld\n", SZ_64K);
}
size = (128 * 1024);
if (size != SZ_128K) {
unit_return_fail(m, "Size 128K Mismatch : %ld\n", SZ_128K);
}
size = (1024 * 1024);
if (size != SZ_1M) {
unit_return_fail(m, "Size 1M Mismatch : %ld\n", SZ_1M);
}
size = (16 * 1024 * 1024);
if (size != SZ_16M) {
unit_return_fail(m, "Size 16M Mismatch : %ld\n", SZ_16M);
}
size = (32 * 1024 * 1024);
if (size != SZ_32M) {
unit_return_fail(m, "Size 32M Mismatch : %ld\n", SZ_32M);
}
size = (256 * 1024 * 1024);
if (size != SZ_256M) {
unit_return_fail(m, "Size 256M Mismatch : %ld\n", SZ_256M);
}
size = (512 * 1024 * 1024);
if (size != SZ_512M) {
unit_return_fail(m, "Size 512M Mismatch : %ld\n", SZ_512M);
}
size = (1024 * 1024 * 1024);
if (size != SZ_1G) {
unit_return_fail(m, "Size 1G Mismatch : %ld\n", SZ_1G);
}
size = ((unsigned long)4 * (unsigned long)(1024 * 1024 * 1024));
if (size != SZ_4G) {
unit_return_fail(m, "Size 4G Mismatch : %ld\n", SZ_4G);
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_sizes_tests[] = {
UNIT_TEST(size_defines, test_size_defines, NULL, 0),
};
UNIT_MODULE(posix_sizes, posix_sizes_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,71 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-sizes
* @{
*
* Software Unit Test Specification for posix-sizes
*/
#ifndef __UNIT_POSIX_SIZES_H__
#define __UNIT_POSIX_SIZES_H__
#include <stdlib.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/sizes.h>
/**
* Test specification for test_size_defines
*
* Description: Test the values of various size defines.
*
* Test Type: Feature
*
* Targets: SZ_256, SZ_1K, SZ_4K, SZ_64K, SZ_128K, SZ_1M, SZ_16M, SZ_32M,
* SZ_256M, SZ_512M, SZ_1G, SZ_4G.
*
* Inputs:
* None
*
* Steps:
* 1) Assign a local variable with the expected value of the define that
* has to compared.
* 2) Compare the value of the local variable with the value of the
* define.
* 3) Return fail if the value of the define does not match with the
* expected value stored in local variable.
* 4) Repeat steps 1 - 3 for all the sizes defined in the unit.
*
* Output:
* The test returns PASS if the values of #defines match with the respective
* expected value.
* The test returns FAIL if there is a mismatch between defined value and
* the expected value.
*
*/
int test_size_defines(struct unit_module *m, struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_SIZES_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 = posix-thread.o
MODULE = posix-thread
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=posix-thread
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=posix-thread
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,309 @@
/*
* 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 <stdlib.h>
#include <unistd.h>
#include <unit/io.h>
#include <unit/unit.h>
#include "posix-thread.h"
#define UNIT_TEST_THREAD_PRIORITY 5
struct test_thread_args {
bool use_priority;
bool check_stop;
bool stop_graceful;
bool use_name;
bool stop_repeat;
bool ret_err;
bool skip_callback;
};
struct unit_test_thread_data {
int thread_created;
int check_priority;
int thread_priority;
int check_stop;
int callback_invoked;
int use_return;
};
static struct test_thread_args create_normal = {
.use_priority = false,
.check_stop = false,
.stop_graceful = false,
.use_name = true,
.stop_repeat = false,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args create_normal_noname = {
.use_priority = false,
.check_stop = false,
.stop_graceful = false,
.use_name = false,
.stop_repeat = false,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args create_normal_errret = {
.use_priority = false,
.check_stop = false,
.stop_graceful = false,
.use_name = true,
.stop_repeat = false,
.ret_err = true,
.skip_callback = false
};
static struct test_thread_args create_priority = {
.use_priority = true,
.check_stop = false,
.stop_graceful = false,
.use_name = true,
.stop_repeat = false,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args create_priority_noname = {
.use_priority = true,
.check_stop = false,
.stop_graceful = false,
.use_name = false,
.stop_repeat = false,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args check_stop = {
.use_priority = false,
.check_stop = true,
.stop_graceful = false,
.use_name = true,
.stop_repeat = false,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args check_stop_repeat = {
.use_priority = false,
.check_stop = true,
.stop_graceful = false,
.use_name = true,
.stop_repeat = true,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args stop_graceful = {
.use_priority = false,
.check_stop = true,
.stop_graceful = true,
.use_name = true,
.stop_repeat = false,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args stop_graceful_repeat = {
.use_priority = false,
.check_stop = true,
.stop_graceful = true,
.use_name = true,
.stop_repeat = true,
.ret_err = false,
.skip_callback = false
};
static struct test_thread_args stop_graceful_skip_callback = {
.use_priority = false,
.check_stop = true,
.stop_graceful = true,
.use_name = true,
.stop_repeat = false,
.ret_err = false,
.skip_callback = true
};
static struct nvgpu_thread test_thread;
static struct unit_test_thread_data test_data;
static int test_thread_fn(void *args)
{
int policy;
struct sched_param param;
struct unit_test_thread_data *data;
(void) memset(&param, 0, sizeof(struct sched_param));
data = (struct unit_test_thread_data *)args;
if (data->check_priority) {
pthread_getschedparam(pthread_self(), &policy, &param);
data->thread_priority = param.sched_priority;
}
data->thread_created = 1;
if (data->check_stop) {
while (!nvgpu_thread_should_stop(&test_thread)) {
usleep(2);
}
}
if (data->use_return) {
return (data->use_return);
}
return 0;
}
static void test_thread_stop_graceful_callback(void *args)
{
struct unit_test_thread_data *data;
data = (struct unit_test_thread_data *)args;
data->callback_invoked = 1;
}
int test_thread_cycle(struct unit_module *m, struct gk20a *g, void *args)
{
int ret;
struct test_thread_args *test_args = (struct test_thread_args *)args;
memset(&test_thread, 0, sizeof(struct nvgpu_thread));
memset(&test_data, 0, sizeof(struct unit_test_thread_data));
if (test_args->check_stop == true) {
test_data.check_stop = 1;
}
if (test_args->use_priority == false) {
if (test_args->use_name == true) {
if (test_args->ret_err == true) {
test_data.use_return = 1;
}
ret = nvgpu_thread_create(&test_thread, &test_data,
test_thread_fn,
"test_thread");
} else {
ret = nvgpu_thread_create(&test_thread, &test_data,
test_thread_fn,
NULL);
}
} else {
test_data.check_priority = 1;
if (test_args->use_name == true) {
ret = nvgpu_thread_create_priority(&test_thread,
&test_data, test_thread_fn,
UNIT_TEST_THREAD_PRIORITY,
"test_thread_priority");
} else {
ret = nvgpu_thread_create_priority(&test_thread,
&test_data, test_thread_fn,
UNIT_TEST_THREAD_PRIORITY,
NULL);
}
}
if (ret != 0) {
if (test_args->use_priority == true && ret == 1) {
unit_info(m, "No permission to set thread priority\n");
unit_info(m, "Return PASS\n");
return UNIT_SUCCESS;
}
unit_return_fail(m, "Thread creation failed %d\n", ret);
}
while (!test_data.thread_created) {
unit_info(m, "Waiting for thread creation\n");
usleep(10);
}
if (test_args->use_priority == true) {
if (test_data.thread_priority != UNIT_TEST_THREAD_PRIORITY) {
unit_return_fail(m, "Thread priority %d mismatch\n",
test_data.thread_priority);
}
}
if (test_args->check_stop == true) {
if (!nvgpu_thread_is_running(&test_thread)) {
unit_return_fail(m, "Thread running status is wrong\n");
}
if (test_args->stop_graceful == false) {
nvgpu_thread_stop(&test_thread);
if (test_args->stop_repeat == true) {
nvgpu_thread_stop(&test_thread);
}
} else {
if (test_args->skip_callback == false) {
nvgpu_thread_stop_graceful(&test_thread,
test_thread_stop_graceful_callback,
&test_data);
if (!test_data.callback_invoked) {
unit_return_fail(m,
"Callback not invoked\n");
}
} else {
nvgpu_thread_stop_graceful(&test_thread,
NULL,
&test_data);
}
if (test_args->stop_repeat == true) {
test_data.callback_invoked = 0;
nvgpu_thread_stop_graceful(&test_thread,
test_thread_stop_graceful_callback,
&test_data);
if (test_data.callback_invoked) {
unit_return_fail(m,
"Callback invoked\n");
}
}
}
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_thread_tests[] = {
UNIT_TEST(create, test_thread_cycle, &create_normal, 0),
UNIT_TEST(create_noname, test_thread_cycle, &create_normal_noname, 0),
UNIT_TEST(create_noname_errret, test_thread_cycle, &create_normal_errret, 0),
UNIT_TEST(create_priority, test_thread_cycle, &create_priority, 0),
UNIT_TEST(create_priority_noname, test_thread_cycle, &create_priority_noname, 0),
UNIT_TEST(cycle, test_thread_cycle, &check_stop, 0),
UNIT_TEST(stop_repeat, test_thread_cycle, &check_stop_repeat, 0),
UNIT_TEST(stop_graceful, test_thread_cycle, &stop_graceful, 0),
UNIT_TEST(stop_graceful_repeat, test_thread_cycle, &stop_graceful_repeat, 0),
UNIT_TEST(stop_graceful_skipcb, test_thread_cycle, &stop_graceful_skip_callback, 0),
};
UNIT_MODULE(posix_thread, posix_thread_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,127 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-thread
* @{
*
* Software Unit Test Specification for posix-thread
*/
#ifndef __UNIT_POSIX_THREAD_H__
#define __UNIT_POSIX_THREAD_H__
#include <nvgpu/thread.h>
/**
* Test specification for test_thread_cycle
*
* Description: Test the various functionalities provided by Threads unit.
* Main functionalities that has to be tested in Threads unit are as follows,
* 1) Thread creation
* 2) Thread creation with a priority value
* 3) Thread stop
* 4) Stop thread gracefully
* test_thread_cycle function tests all the above mentioned functionalities
* based on the input arguments.
*
* Test Type: Feature
*
* Targets: nvgpu_thread_create, nvgpu_thread_create_priority,
* nvgpu_thread_is_running, nvgpu_thread_stop,
* nvgpu_thread_stop_graceful, nvgpu_thread_should_stop,
* nvgpu_thread_join
*
* Inputs:
* 1) Pointer to test_thread_args as function parameter
* 2) Global instance of struct nvgpu_thread
* 3) Global instance of struct unit_test_thread_data
*
* Steps:
* Thread creation
* 1) Reset all global and shared variables to 0.
* 2) Create thread using nvgpu_thread_create.
* 3) Check the return value from nvgpu_thread_create for error.
* 4) Wait for the thread to be created by polling for a shared variable.
* 5) Return Success once the thread function is called and the shared
* variable is set which indicates a successful thread creation.
*
* Thread creation with a priority value
* 1) Reset all global and shared variables to 0.
* 2) Create thread using nvgpu_thread_create_priority
* 3) Check the return value from nvgpu_thread_create_priority for error.
* 4) Wait for the thread to be created by polling for a shared variable.
* 5) Upon successful creation of the thread, confirm the priority of the
* thread to be same as requested priority.
* 6) In some host machines, permission is not granted to create threads
* with priority. In that case skip the test by returning PASS.
* 7) Return PASS if the thread is created with requested priority.
*
* Thread stop
* 1) Follow steps 1 - 4 of Thread creation scenario.
* 2) The created thread does not exit unconditionally in this case.
* 3) It polls for the stop flag to be set.
* 4) The main thread checks the status of the created thread and confirms
* it to be running.
* 5) Request the thread to stop by calling nvgpu_thread_stop.
* 6) Created thread detects this inside the poll loop and exits.
* 7) Main thread continues once the created thread exits.
* 8) If stop_repeat flag is set, invoke nvgpu_thread_stop again. This is done
* to increase branch coverage.
* 9) Return PASS.
*
* Stop thread gracefully
* 1) Follow steps 1 - 4 of Thread stop scenario.
* 2) Call the function nvgpu_thread_stop_graceful. Depending on the flag
* skip_callback, either NULL or a function is passed as callback parameter
* to be called for graceful exit.
* 3) Created thread detects the stop request and exits.
* 4) Main thread continues after the created thread exits.
* 5) If skip_callback flag is set to false, confirm if the call back function
* was called by checking a shared variable value.
* 6) If stop_repeat flag is set, invoke nvgpu_thread_stop_graceful function
* again. This invocation should not call the callback function as the
* thread was already stopped in step 5.
* 7) Return PASS.
*
* Output:
* The output for each test scenario is as follows,
* 1) Thread creation
* Return PASS if thread creation is successful else return FAIL.
*
* 2) Thread creation with a priority value
* Return PASS if thread creation with priority is successful
* else return FAIL. Also return PASS if permission is denied for creating
* a thread with priority.
*
* 3) Thread stop
* Return PASS if the created thread is stopped based on the request from
* main thread. Else return FAIL.
*
* 4) Stop thread gracefully
* Return PASS if the callback function is called and the created thread is
* stopped based on the request from main thread.
*
*/
int test_thread_cycle(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_THREAD_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 = posix-timers.o
MODULE = posix-timers
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=posix-timers
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=posix-timers
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,419 @@
/*
* 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 <stdlib.h>
#include <unistd.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/timers.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include "posix-timers.h"
struct test_timer_args {
bool counter_timer;
};
static struct test_timer_args init_args = {
.counter_timer = true,
};
#define TEST_TIMER_COUNT 10
/* The value should be kept below 999 since it is used to calculate
* the duration paramater to usleep. This will ensure that the duration
* value passed to usleep is less than 1000000.
*/
#define TEST_TIMER_DURATION 10
static struct nvgpu_timeout test_timeout;
int test_timer_init(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
unsigned int duration;
unsigned long flags;
struct test_timer_args *test_args = (struct test_timer_args *)args;
if (test_args->counter_timer == true) {
duration = TEST_TIMER_COUNT;
flags = NVGPU_TIMER_RETRY_TIMER;
} else {
duration = TEST_TIMER_DURATION;
flags = NVGPU_TIMER_CPU_TIMER;
}
ret = nvgpu_timeout_init(g, &test_timeout,
duration,
flags);
if (ret != 0) {
unit_return_fail(m, "Timer init failed %d\n", ret);
}
if (test_timeout.g != g) {
unit_return_fail(m, "Timer g struct mismatch %d\n", ret);
}
if (test_timeout.flags != flags) {
unit_return_fail(m, "Timer flags mismatch %d\n", ret);
}
return UNIT_SUCCESS;
}
int test_timer_init_err(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret, i;
for (i = 0; i < 12; i++) {
memset(&test_timeout, 0, sizeof(struct nvgpu_timeout));
/* nvgpu_tiemout_init accepts only BIT(0), BIT(8), and BIT(9) as
* valid flag bits. So ret should be EINVAL */
ret = nvgpu_timeout_init(g, &test_timeout, 10, (1 << i));
if ((i == 0) || (i == 8) || (i == 9)) {
if (ret != 0) {
unit_return_fail(m,
"Timer init failed %d\n",
ret);
}
} else {
if (ret != -EINVAL) {
unit_return_fail(m,
"Timer init with invalid flag %d\n",
ret);
}
}
}
/* BIT(0), BIT(8) and BIT(9) set. Return value should be 0 */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x301);
if (ret != 0) {
unit_return_fail(m,"Timer init failed with flag 0x301\n");
}
/* BIT(8) and BIT(9) set. Return value should be 0 */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x300);
if (ret != 0) {
unit_return_fail(m,"Timer init failed with flag 0x300\n");
}
/* BIT(0) and BIT(8) set. Return value should be 0 */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x101);
if (ret != 0) {
unit_return_fail(m,"Timer init failed with flag 0x101\n");
}
/* BIT(0) and BIT(9) set. Return value should be 0 */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x201);
if (ret != 0) {
unit_return_fail(m,"Timer init failed with flag 0x201\n");
}
/* BIT(0), BIT(7) and BIT(9) set. Return value should be -EINVAL */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x281);
if (ret != -EINVAL) {
unit_return_fail(m,"Timer init failed with flag 0x281\n");
}
/* BIT(5), BIT(7) and BIT(9) set. Return value should be -EINVAL */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x2A0);
if (ret != -EINVAL) {
unit_return_fail(m,"Timer init failed with flag 0x2A0\n");
}
/* BIT(1), BIT(2) and BIT(3) set. Return value should be -EINVAL */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x00E);
if (ret != -EINVAL) {
unit_return_fail(m,"Timer init failed with flag 0x00E\n");
}
/* BIT(1) to BIT(7) set. Return value should be -EINVAL */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x07E);
if (ret != -EINVAL) {
unit_return_fail(m,"Timer init failed with flag 0x07E\n");
}
/* All bits set. Return value should be -EINVAL */
ret = nvgpu_timeout_init(g, &test_timeout, 10, 0xFFFFFFFFFFFFFFFF);
if (ret != -EINVAL) {
unit_return_fail(m,"Timer init failed with flag all 1s\n");
}
return UNIT_SUCCESS;
}
int test_timer_counter(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
memset(&test_timeout, 0, sizeof(struct nvgpu_timeout));
ret = nvgpu_timeout_init(g, &test_timeout,
TEST_TIMER_COUNT,
NVGPU_TIMER_RETRY_TIMER);
if (ret != 0) {
unit_return_fail(m, "Timer init failed %d\n", ret);
}
do {
usleep(1);
} while (nvgpu_timeout_expired(&test_timeout) == 0);
if (!nvgpu_timeout_peek_expired(&test_timeout)) {
unit_return_fail(m, "Counter mismatch %d\n",
test_timeout.retries.attempted);
}
return UNIT_SUCCESS;
}
int test_timer_duration(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
memset(&test_timeout, 0, sizeof(struct nvgpu_timeout));
ret = nvgpu_timeout_init(g, &test_timeout,
TEST_TIMER_DURATION,
NVGPU_TIMER_CPU_TIMER);
if (ret != 0) {
unit_return_fail(m, "Timer init failed %d\n", ret);
}
/*
* Timer should not be expired.
* However, test execution may not be atomic and might get preempted.
* In that scenario, the return value might not be zero.
* Reading timer value also takes many cycles, hence it is difficult
* to confirm if timer timedout before set timeout value.
* So, here we print an error message if return value is not zero.
*/
ret = nvgpu_timeout_expired(&test_timeout);
if (ret != 0) {
unit_err(m,
"Duration timer expired when not expected %d\n", ret);
}
/* Sleep for TEST_TIMER_DURATION */
usleep((TEST_TIMER_DURATION * 1000));
do {
usleep(10);
ret = nvgpu_timeout_expired(&test_timeout);
} while (ret == 0);
if (ret != -ETIMEDOUT) {
unit_return_fail(m, "Duration timer not expired %d\n", ret);
}
if (!nvgpu_timeout_peek_expired(&test_timeout)) {
unit_return_fail(m, "Duration failure\n");
}
return UNIT_SUCCESS;
}
int test_timer_fault_injection(struct unit_module *m,
struct gk20a *g, void *args)
{
int ret;
struct nvgpu_posix_fault_inj *timers_fi =
nvgpu_timers_get_fault_injection();
memset(&test_timeout, 0, sizeof(struct nvgpu_timeout));
ret = nvgpu_timeout_init(g, &test_timeout,
TEST_TIMER_DURATION,
NVGPU_TIMER_CPU_TIMER);
if (ret != 0) {
unit_return_fail(m, "Timer init failed %d\n", ret);
}
nvgpu_posix_enable_fault_injection(timers_fi, true, 1);
/* Timer should not be expired */
ret = nvgpu_timeout_expired(&test_timeout);
if (ret != 0) {
unit_return_fail(m,
"Fault injected timer expired when not expected %d\n",
ret);
}
/* Timer should be expired */
ret = nvgpu_timeout_expired(&test_timeout);
if (ret != -ETIMEDOUT) {
unit_return_fail(m,
"Fault injected timer expired when not expected %d\n",
ret);
}
nvgpu_posix_enable_fault_injection(timers_fi, false, 0);
/* Sleep for TEST_TIMER_DURATION */
usleep((TEST_TIMER_DURATION * 1000));
do {
usleep(10);
ret = nvgpu_timeout_expired(&test_timeout);
} while (ret == 0);
if (ret != -ETIMEDOUT) {
unit_return_fail(m, "Fault injected timer not expired %d\n",
ret);
}
return UNIT_SUCCESS;
}
int test_timer_delay(struct unit_module *m,
struct gk20a *g, void *args)
{
signed long ts_before, ts_after, delay;
ts_before = nvgpu_current_time_us();
nvgpu_udelay(5000);
ts_after = nvgpu_current_time_us();
delay = ts_after - ts_before;
delay /= 1000;
if (delay < 5) {
unit_return_fail(m,
"Delay Duration incorrect\n");
}
ts_before = nvgpu_current_time_us();
nvgpu_usleep_range(5000, 10000);
ts_after = nvgpu_current_time_us();
delay = ts_after - ts_before;
delay /= 1000;
if (delay < 5) {
unit_return_fail(m,
"Delay Duration incorrect\n");
}
return UNIT_SUCCESS;
}
int test_timer_msleep(struct unit_module *m,
struct gk20a *g, void *args)
{
signed long ts_before, ts_after, delay;
delay = 0;
ts_before = nvgpu_current_time_ms();
nvgpu_msleep(5);
ts_after = nvgpu_current_time_ms();
delay = ts_after - ts_before;
if (delay < 5) {
unit_return_fail(m, "Sleep Duration incorrect\n");
}
return UNIT_SUCCESS;
}
#ifdef CONFIG_NVGPU_NON_FUSA
int test_timer_hrtimestamp(struct unit_module *m,
struct gk20a *g, void *args)
{
unsigned long cycles_read, cycles_bkp;
int i;
cycles_read = 0;
cycles_bkp = 0;
for (i = 0; i < 50; i++) {
cycles_read = nvgpu_hr_timestamp();
if (cycles_read < cycles_bkp) {
unit_return_fail(m,
"HR cycle value error %ld < %ld\n",
cycles_read, cycles_bkp);
}
cycles_bkp = cycles_read;
usleep(1);
}
return UNIT_SUCCESS;
}
#endif
int test_timer_compare(struct unit_module *m,
struct gk20a *g, void *args)
{
int i;
signed long time_ms, time_ns;
i = 0;
time_ms = 0;
time_ns = 0;
while (i < 10) {
time_ms = nvgpu_current_time_ms();
time_ns = nvgpu_current_time_ns();
time_ns /= 1000000;
if (time_ns < time_ms) {
unit_return_fail(m,
"Err, ms and ns mismatch\n");
}
i++;
usleep(1000);
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_timers_tests[] = {
UNIT_TEST(init, test_timer_init, &init_args, 0),
UNIT_TEST(init_err, test_timer_init_err, NULL, 0),
UNIT_TEST(counter, test_timer_counter, NULL, 0),
UNIT_TEST(duration, test_timer_duration, NULL, 0),
UNIT_TEST(fault_injection, test_timer_fault_injection, NULL, 0),
UNIT_TEST(delay, test_timer_delay, NULL, 0),
UNIT_TEST(msleep, test_timer_msleep, NULL, 0),
#ifdef CONFIG_NVGPU_NON_FUSA
UNIT_TEST(hr_cycles, test_timer_hrtimestamp, NULL, 0),
#endif
UNIT_TEST(compare, test_timer_compare, NULL, 0),
};
UNIT_MODULE(posix_timers, posix_timers_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,313 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-timers
* @{
*
* Software Unit Test Specification for posix-timers
*/
#ifndef __UNIT_POSIX_TIMERS_H__
#define __UNIT_POSIX_TIMERS_H__
/**
* Test specification for test_timer_init
*
* Description: Test the timer initialization routine.
*
* Test Type: Feature
*
* Targets: nvgpu_timeout_init
*
* Inputs:
* 1) The type of timer to be tested is passed as an argument to the test.
* 2) Global defines for flag and duration values.
* 3) Global nvgpu_timeout structure instance.
*
* Steps:
* 1) Check for the type of timer to be tested.
* 2) Populate the flags and duration values depending on the timer type.
* 3) Invoke the timer init function.
* 4) Check the return value for errors.
* 5) Check the internal parameters in nvgpu_timeout structure to ensure
* proper initialisation.
*
* Output:
* The test returns PASS if the return value from timer init function
* indicates success and the internal parameter values in nvgpu_timeout
* structure is initialised as per the passed arguments.
* Test returns FAIL if timer init function fails or if any of the
* parameters inside the nvgpu_timeout struct is not initialised properly.
*
*/
int test_timer_init(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_init_err
*
* Description: Test the timer initialisation routine error path.
*
* Test Type: Boundary values
*
* Targets: nvgpu_timeout_init
*
* Inputs:
* 1) Global nvgpu_timeout structure instance.
*
* Steps:
* 1) Invoke timer initialisation routine in loop with different value for
* flags parameter for each invocation.
* 2) Check for the corresponding return value. The timer initialisation
* function should return error for invalid flag values and return success
* for valid flag values.
*
* Output:
* The test returns PASS if the initialisation routine returns an appropriate
* return value as per the flag value passed for each invocation.
* The test returns FAIL if the initialisation routine does not return the
* expected value for a particular flag for any of the invocation.
*
*/
int test_timer_init_err(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_counter
*
* Description: Test the counter based timer functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_timeout_init, nvgpu_timeout_expired,
* nvgpu_timeout_peek_expired
*
* Input:
* 1) Global nvgpu_timeout structure instance.
* 2) Global defines for flag and duration parameters.
*
* Steps:
* 1) Reset the global nvgpu_timeout structure with all 0s.
* 2) Initialise the timeout structure.
* 3) Check the return value for error.
* 4) Loop and check for the timer expiry. Sleep is introduced
* between each loop.
* 5) Confirm the status of the timer expiry by verifying the
* counter value.
*
* Output:
* Test returns PASS if the timer expires after the programmed
* counter value.
* Test returns FAIL if the initialisation routine returns error or
* timer expires before the programmed counter value is reached.
*
*/
int test_timer_counter(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_duration
*
* Description: Test the duration based timer functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_timeout_init, nvgpu_timeout_expired,
* nvgpu_timeout_peek_expired
*
* Input:
* 1) Global nvgpu_timeout structure instance.
* 2) Global defines for flag and duration parameters.
*
* Steps:
* 1) Reset the global nvgpu_timeout structure to all 0s.
* 2) Initialise the timeout structure.
* 3) Check the return value for error.
* 4) Check for timer status. Confirm that timer has not expired.
* 5) Sleep for the required duration + 500ms to ensure the timer expires.
* 6) Check for the timer status.
* 7) Reconfirm the timer status.
*
* Output:
* Test returns PASS if the timer expires after the programmed
* duration.
* Test returns FAIL if initialisation routine returns error, if the timer
* does not expire after programmed duration or if timer expires before
* programmed duration.
*
*/
int test_timer_duration(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_duration
*
* Description: Test fault injection timer functionality.
*
* Test Type: Feature
*
* Input:
* 1) Global nvgpu_timeout structure instance.
* 2) Global defines for flag and duration parameters.
*
* Steps:
* 1) Reset the global nvgpu_timeout structure to all 0s.
* 2) Initialise the timeout structure.
* 3) Check the return value for error.
* 4) Initialize fault injection counter and enable fault injection.
* 5) Check for the timer status. Confirm that return value is 0.
* 6) Check for the timer status. Confirm that return value is 0.
* 7) Sleep for the required duration + 500ms to ensure the timer expires.
* 8) Check for the timer status.
*
* Output:
* Test returns PASS if the timer expires after the programmed
* duration.
* Test returns FAIL if the initialisation routine returns error, if function
* returns non-zero value when fault injection is enabled or if the timer does
* not expire even after the programmed duration.
*
*/
int test_timer_fault_injection(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_delay
*
* Description: Test the delay functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_current_time_us, nvgpu_udelay,
* nvgpu_usleep_range
*
* Input: None.
*
* Steps:
* 1) Get the current time in us.
* 2) Delay the execution using nvpgu_udelay function.
* 3) Get the time after the delay function is executed.
* 4) Calculate the difference between both timestamps.
* 5) Convert it into msec.
* 6) If the difference is less than the duration for which the
* delay was requested, return fail.
* 7) Continue steps 1-6 for the wrapper api nvgpu_usleep_range
* which internally uses nvgpu_udelay itself.
*
* Output:
* Test returns PASS if the delay function actually delays the execution
* for required amount of time. It also returns PASS if there is a
* reordering of instructions resulting in the test check being invalid
* and the test is skipped by returning PASS.
* Test returns FAIL if the delay function returns before the required
* duration.
*
*/
int test_timer_delay(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_msleep
*
* Description: Test the sleep functionality.
*
* Test Type: Feature
*
* Targets: nvgpu_current_time_ms, nvgpu_msleep
*
* Input: None.
*
* Steps:
* 1) Get the current time in ms.
* 2) Call sleep function for 5ms.
* 3) Get the time after the sleep call.
* 4) Calculate the difference between both the timestamps.
* 5) Compare the difference to deduce the test result.
*
* Output:
* Test returns PASS if the sleep function is completed for required duration.
* Test returns FAIL if the sleep function returns before the requested
* duration.
*
*/
int test_timer_msleep(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_hrtimestamp
*
* Description: Test the high resolution counter based functionalities.
*
* Test Type: Feature
*
* Targets: nvgpu_hr_timestamp
*
* Input: None.
*
* Steps:
* 1) Initialise two counter variables to 0.
* 2) Read the value of HR counter into one of the counter variables.
* 3) Compare the value of read counter value with the bkp counter value.
* 4) If read counter variable is less than the previously read counter value
* return fail.
* 5) Store the read counter value in bkp counter value.
* 6) Suspend execution by calling usleep.
* 7) Loop steps 1 - 6 for multiple times.
*
* Output:
* Test returns PASS if for every read of HR counter, the value returned is
* either greater than or equal to the previous value.
* Test returns FAIL if any of the subsequent read of HR counter returns
* a value less than the previous value.
*
*/
int test_timer_hrtimestamp(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for test_timer_compare
*
* Description: Compare the timers in various resoutions.
*
* Test Type: Feature
*
* Targets: nvgpu_current_time_ms, nvgpu_current_time_ns
*
* Input: None.
*
* Steps:
* 1) Initialise two timestamp variables.
* 2) Read the time in ms and store in one timestamp variable.
* 3) Read the time in ns and store in the second timestamp variable.
* 4) Do the necessary conversion to make both timers in same resolution.
* 5) Compare the timer values to determine the test results.
*
* Output:
* Test returns PASS if various timer resolutions match each other.
* Test returns FAIL if various timer resolutions does not match with
* each other.
*
*/
int test_timer_compare(struct unit_module *m,
struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_TIMERS_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 = posix-utils.o
MODULE = posix-utils
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-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,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# 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.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=posix-utils
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,628 @@
/*
* Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* 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 <stdint.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/utils.h>
#include <nvgpu/barrier.h>
#include "posix-utils.h"
#define KHZ (1000U)
#define MHZ (1000000U)
#define ARRAY1_SIZE 4
#define ARRAY2_SIZE 10
#define PAGE_ALIGN_TEST_VALUE 0x3fffffff
#define ALIGN_TEST_VALUE 0xffff
#define ALIGN_WITH_VALUE 0x10
#define ALIGN_WITH_MASK 0x3
#define TO_ROUND_VALUE 11U
#define ROUND_BY_VALUE 4U
#define ROUND_UP_RESULT 12U
#define ROUND_DOWN_RESULT 8U
struct test_container {
uint32_t var1;
uint32_t var2;
};
struct test_container cont = {20, 30};
/*
* Test to ensure the EXPECT_BUG construct works as intended by making sure it
* behaves properly when BUG is called or not.
* In the event that EXPECT_BUG is completely broken, the call to BUG() would
* cause the unit to crash and report a failure correctly.
*/
int test_hamming_weight(struct unit_module *m,
struct gk20a *g, void *args)
{
unsigned int result;
unsigned int i;
uint8_t hwt_8bit;
uint16_t hwt_16bit;
uint32_t hwt_32bit;
uint64_t hwt_64bit;
for (i = 0; i < 8; i++) {
hwt_8bit = (unsigned int) 1 << i;
result = nvgpu_posix_hweight8(hwt_8bit);
if (result != 1) {
unit_return_fail(m,
"8 bit hwt failed for %d\n", hwt_8bit);
}
}
for (i = 0; i < 16; i++) {
hwt_16bit = (unsigned int) 1 << i;
result = nvgpu_posix_hweight16(hwt_16bit);
if (result != 1) {
unit_return_fail(m,
"16 bit hwt failed for %d\n", hwt_16bit);
}
}
for (i = 0; i < 32; i++) {
hwt_32bit = (unsigned int) 1 << i;
result = nvgpu_posix_hweight32(hwt_32bit);
if (result != 1) {
unit_return_fail(m,
"32 bit hwt failed for %d\n", hwt_32bit);
}
}
for (i = 0; i < 32; i++) {
hwt_32bit = (unsigned int) 1 << i;
result = hweight32(hwt_32bit);
if (result != 1) {
unit_return_fail(m,
"hweight32 failed for %d\n", hwt_32bit);
}
}
for (i = 0; i < 64; i++) {
hwt_64bit = (unsigned long) 1 << i;
result = nvgpu_posix_hweight64(hwt_64bit);
if (result != 1) {
unit_return_fail(m,
"64 bit hwt failed for %lx\n", hwt_64bit);
}
}
for (i = 0; i < 64; i++) {
hwt_64bit = (unsigned long) 1 << i;
result = hweight_long(hwt_64bit);
if (result != 1) {
unit_return_fail(m,
"hweight_long failed for %lx\n", hwt_64bit);
}
}
hwt_8bit = 0x0;
result = nvgpu_posix_hweight8(hwt_8bit);
if (result != 0) {
unit_return_fail(m,
"8 bit hwt failed for %d\n", hwt_8bit);
}
hwt_8bit = 0xff;
result = nvgpu_posix_hweight8(hwt_8bit);
if (result != 8) {
unit_return_fail(m,
"8 bit hwt failed for %d\n", hwt_8bit);
}
hwt_16bit = 0x0;
result = nvgpu_posix_hweight16(hwt_16bit);
if (result != 0) {
unit_return_fail(m,
"16 bit hwt failed for %d\n", hwt_16bit);
}
hwt_16bit = 0xffff;
result = nvgpu_posix_hweight16(hwt_16bit);
if (result != 16) {
unit_return_fail(m,
"16 bit hwt failed for %d\n", hwt_16bit);
}
hwt_32bit = 0x0;
result = nvgpu_posix_hweight32(hwt_32bit);
if (result != 0) {
unit_return_fail(m,
"32 bit hwt failed for %d\n", hwt_32bit);
}
hwt_32bit = 0xffffffff;
result = nvgpu_posix_hweight32(hwt_32bit);
if (result != 32) {
unit_return_fail(m,
"32 bit hwt failed for %d\n", hwt_32bit);
}
hwt_32bit = 0x0;
result = hweight32(hwt_32bit);
if (result != 0) {
unit_return_fail(m,
"hweight32 failed for %d\n", hwt_32bit);
}
hwt_32bit = 0xffffffff;
result = hweight32(hwt_32bit);
if (result != 32) {
unit_return_fail(m,
"hweight32 failed for %d\n", hwt_32bit);
}
hwt_64bit = 0x0;
result = nvgpu_posix_hweight64(hwt_64bit);
if (result != 0) {
unit_return_fail(m,
"64 bit hwt failed for %ld\n", hwt_64bit);
}
hwt_64bit = 0xffffffffffffffff;
result = nvgpu_posix_hweight64(hwt_64bit);
if (result != 64) {
unit_return_fail(m,
"64 bit hwt failed for %ld\n", hwt_64bit);
}
hwt_64bit = 0x0;
result = hweight_long(hwt_64bit);
if (result != 0) {
unit_return_fail(m,
"hweight_long failed for %ld\n", hwt_64bit);
}
hwt_64bit = 0xffffffffffffffff;
result = hweight_long(hwt_64bit);
if (result != 64) {
unit_return_fail(m,
"hweight_long failed for %ld\n", hwt_64bit);
}
return UNIT_SUCCESS;
}
int test_be32tocpu(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t pattern;
uint32_t result;
uint8_t *ptr;
pattern = 0xaabbccdd;
ptr = (uint8_t*)&pattern;
result = be32_to_cpu(pattern);
if (*ptr == 0xdd) {
if (result != 0xddccbbaa) {
unit_return_fail(m,
"be32tocpu failed for %x %x\n",
pattern, result);
}
}
return UNIT_SUCCESS;
}
int test_minmax(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t i;
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t result;
a = 10;
b = 20;
c = 30;
for (i = 0; i < 10; i++) {
result = min(a, b);
if (result != a) {
unit_return_fail(m, "min failure %d\n", result);
}
result = min(b, a);
if (result != a) {
unit_return_fail(m, "min failure %d\n", result);
}
a += 5;
b += 5;
}
a = 100;
b = 200;
c = 300;
for (i = 0; i < 10; i++) {
result = min3(a, b, c);
if (result != a) {
unit_return_fail(m, "min3 failure %d\n", result);
}
result = min3(a, c, b);
if (result != a) {
unit_return_fail(m, "min3 failure %d\n", result);
}
result = min3(b, a, c);
if (result != a) {
unit_return_fail(m, "min3 failure %d\n", result);
}
result = min3(b, c, a);
if (result != a) {
unit_return_fail(m, "min3 failure %d\n", result);
}
result = min3(c, a, b);
if (result != a) {
unit_return_fail(m, "min3 failure %d\n", result);
}
result = min3(c, b, a);
if (result != a) {
unit_return_fail(m, "min3 failure %d\n", result);
}
a += 5;
b += 5;
c += 5;
}
b = 2000;
c = 3000;
for (i = 0; i < 10; i++) {
result = min_t(uint32_t, b, c);
if (result != b) {
unit_return_fail(m, "min_t failure %d\n", result);
}
result = min_t(uint32_t, c, b);
if (result != b) {
unit_return_fail(m, "min_t failure %d\n", result);
}
b += 100;
c += 100;
}
a = 1000;
b = 2000;
for (i = 0; i < 10; i++) {
result = max(a, b);
if (result != b) {
unit_return_fail(m, "max failure %d\n", result);
}
result = max(b, a);
if (result != b) {
unit_return_fail(m, "max failure %d\n", result);
}
a += 100;
b += 100;
}
return UNIT_SUCCESS;
}
int test_arraysize(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t result;
uint32_t array1[ARRAY1_SIZE] = {0};
uint64_t array2[ARRAY2_SIZE] = {0};
result = ARRAY_SIZE(array1);
if (result != ARRAY1_SIZE) {
unit_return_fail(m, "ARRAY SIZE failure %d\n", result);
}
result = ARRAY_SIZE(array2);
if (result != ARRAY2_SIZE) {
unit_return_fail(m, "ARRAY SIZE failure %d\n", result);
}
return UNIT_SUCCESS;
}
int test_typecheck(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t result;
unsigned int test1;
unsigned long test2;
signed int test3;
signed long test4;
result = IS_UNSIGNED_TYPE(test1);
if (!result) {
unit_return_fail(m,
"IS_UNSIGNED_TYPE failure for uint %d\n", result);
}
result = IS_UNSIGNED_TYPE(test2);
if (!result) {
unit_return_fail(m,
"IS_UNSIGNED_TYPE failure for ulong %d\n", result);
}
result = IS_UNSIGNED_TYPE(test3);
if (result) {
unit_return_fail(m,
"IS_UNSIGNED_TYPE failure for int %d\n", result);
}
result = IS_UNSIGNED_LONG_TYPE(test2);
if (!result) {
unit_return_fail(m,
"IS_UNSIGNED_LONG_TYPE failure for ulong %d\n",
result);
}
result = IS_UNSIGNED_LONG_TYPE(test4);
if (result) {
unit_return_fail(m,
"IS_UNSIGNED_LONG_TYPE failure for long %d\n",
result);
}
result = IS_SIGNED_LONG_TYPE(test2);
if (result) {
unit_return_fail(m,
"IS_SIGNED_LONG_TYPE failure for ulong %d\n",
result);
}
result = IS_SIGNED_LONG_TYPE(test4);
if (!result) {
unit_return_fail(m,
"IS_SIGNED_LONG_TYPE failure for long %d\n",
result);
}
return UNIT_SUCCESS;
}
int test_align_macros(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t result;
unsigned int test1;
test1 = ALIGN_TEST_VALUE;
result = ALIGN_WITH_VALUE;
test1 = NVGPU_ALIGN(test1, result);
if (test1 & (ALIGN_WITH_VALUE - 1)) {
unit_return_fail(m,
"ALIGN failure %x\n", test1);
}
test1 = ALIGN_TEST_VALUE;
result = ALIGN_WITH_MASK;
test1 = ALIGN_MASK(test1, result);
if (test1 & ALIGN_WITH_MASK) {
unit_return_fail(m,
"ALIGN_MASK failure %x\n", test1);
}
test1 = PAGE_ALIGN_TEST_VALUE;
result = PAGE_ALIGN(test1);
if (result & (NVGPU_CPU_PAGE_SIZE - 1)) {
unit_return_fail(m,
"PAGE_ALIGN failure %x\n", result);
}
return UNIT_SUCCESS;
}
int test_round_macros(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t result, i, test1;
for (i = 1; i < 8; i++) {
result = 1U << i;
if (round_mask(test1, result) != (result - 1U)) {
unit_return_fail(m,
"round_mask failure %d\n", result);
}
}
result = ROUND_BY_VALUE;
for (i = 0; i < ROUND_BY_VALUE; i++) {
test1 = (ROUND_DOWN_RESULT + 1U) + i;
if (round_up(test1, result) != ROUND_UP_RESULT) {
unit_return_fail(m, "round_up failure %d %d\n", test1, i);
}
}
result = ROUND_BY_VALUE;
for (i = 0; i < ROUND_BY_VALUE; i++) {
test1 = (ROUND_UP_RESULT - 1U) - i;
if (round_down(test1, result) != ROUND_DOWN_RESULT) {
unit_return_fail(m, "round_down failure\n");
}
}
return UNIT_SUCCESS;
}
int test_write_once(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t result, i, test1;
test1 = 20;
for (i = 0 ; i < 10; i++) {
test1 += 1;
NV_WRITE_ONCE(result, test1);
if (result != test1) {
unit_return_fail(m,
"NV_WRITE_ONCE failure %d\n", result);
}
}
return UNIT_SUCCESS;
}
int test_div_macros(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t result, test1;
uint64_t test2, test5;
test1 = 199/20;
test2 = DIV_ROUND_UP_U64(199, 20);
if (test2 != (test1 + 1)) {
unit_return_fail(m,
"DIV_ROUND_UP_U64 failure %ld\n", test2);
}
test1 = 239/40;
result = DIV_ROUND_UP((uint32_t) 239, (uint32_t) 40);
if (result != (test1 + 1)) {
unit_return_fail(m,
"DIV_ROUND_UP failure %d\n", result);
}
test1 = 640;
result = 100;
do_div(test1, result);
if (test1 != 6) {
unit_return_fail(m,
"do_div failure %d\n", test1);
}
test2 = 800;
test5 = 200;
result = div64_u64(test2, test5);
if (result != (test2/test5)) {
unit_return_fail(m,
"div64_u64 failure %d\n", result);
}
return UNIT_SUCCESS;
}
int test_containerof(struct unit_module *m,
struct gk20a *g, void *args)
{
struct test_container *contptr;
struct test_container *contptr1;
struct test_container *contptr2;
uint32_t *varptr1;
uint32_t *varptr2;
contptr = &cont;
varptr1 = &cont.var1;
varptr2 = &cont.var2;
contptr1 = container_of(varptr1, struct test_container, var1);
contptr2 = container_of(varptr2, struct test_container, var2);
if ((contptr1 != contptr) || (contptr2 != contptr)) {
unit_return_fail(m, "container_of failure\n");
}
return UNIT_SUCCESS;
}
int test_hertzconversion(struct unit_module *m,
struct gk20a *g, void *args)
{
uint32_t i, hz, khz, mhz;
uint64_t long_hz;
for (i = 1; i < 10; i++) {
hz = i * 1000U;
khz = HZ_TO_KHZ(hz);
if (khz != i) {
unit_return_fail(m, "HZ_TO_KHZ failure\n");
}
if (hz != KHZ_TO_HZ(i)) {
unit_return_fail(m, "KHZ_TO_HZ failure\n");
}
hz = i * 1000000U;
mhz = HZ_TO_MHZ(hz);
if (mhz != i) {
unit_return_fail(m, "HZ_TO_MHZ failure\n");
}
long_hz = i * 1000000U;
mhz = HZ_TO_MHZ_ULL(long_hz);
if (mhz != i) {
unit_return_fail(m, "HZ_TO_MHZ_ULL failure\n");
}
}
for (i = 0; i < 10; i++) {
khz = i * 1000U;
mhz = KHZ_TO_MHZ(khz);
if (mhz != i) {
unit_return_fail(m, "KHZ_TO_MHZ failure\n");
}
if (khz != MHZ_TO_KHZ(i)) {
unit_return_fail(m, "MHZ_TO_KHZ failure\n");
}
}
for (i = 0; i < 10; i++) {
hz = i * 1000000;
if (hz != MHZ_TO_HZ_ULL(i)) {
unit_return_fail(m, "MHZ_TO_HZ_ULL failure\n");
}
}
return UNIT_SUCCESS;
}
struct unit_module_test posix_utils_tests[] = {
UNIT_TEST(hweight_test, test_hamming_weight, NULL, 0),
UNIT_TEST(be32tocpu_test, test_be32tocpu, NULL, 0),
UNIT_TEST(minmax_test, test_minmax, NULL, 0),
UNIT_TEST(arraysize_test, test_arraysize, NULL, 0),
UNIT_TEST(typecheck_test, test_typecheck, NULL, 0),
UNIT_TEST(alignmacros_test, test_align_macros, NULL, 0),
UNIT_TEST(roundmacros_test, test_round_macros, NULL, 0),
UNIT_TEST(writeonce_test, test_write_once, NULL, 0),
UNIT_TEST(divmacros_test, test_div_macros, NULL, 0),
UNIT_TEST(containerof_test, test_containerof, NULL, 0),
UNIT_TEST(conversion_test, test_hertzconversion, NULL, 0),
};
UNIT_MODULE(posix_utils, posix_utils_tests, UNIT_PRIO_POSIX_TEST);

View File

@@ -0,0 +1,326 @@
/*
* 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.
*/
/**
* @addtogroup SWUTS-posix-utils
* @{
*
* Software Unit Test Specification for posix-utils
*/
#ifndef __UNIT_POSIX_UTILS_H__
#define __UNIT_POSIX_UTILS_H__
/**
* Test specification for test_hamming_weight
*
* Description: Test the hamming weight implementation.
*
* Test Type: Feature
*
* Targets: nvgpu_posix_hweight8, nvgpu_posix_hweight16,
* nvgpu_posix_hweight32, nvgpu_posix_hweight64,
* hweight32, hweight_long
*
* Inputs: None
*
* Steps:
* 1) Call nvgpu_posix_hweight8 in loop with only the loop index bit position
* set.
* 2) Return FAIL if the return value from nvgpu_posix_hweight8 is not equal
* to 1 in any of the iterations.
* 3) Repeat steps 1 and 2 for nvgpu_posix_hweight16, nvgpu_posix_hweight32
* nvgpu_posix_hweight64, hweight32 and hweight_long.
* 4) Call nvgpu_posix_hweight8 with input parameter set as 0.
* 5) Return FAIL if the return value from nvgpu_posix_hweight8 is not equal
* to 0.
* 6) Call nvgpu_posix_hweight8 with input parameter set to maximum value.
* 7) Return FAIL if the return value from nvgpu_posix_hweight8 is not equal
* to the number of bits in the input parameter.
* 8) Repeat steps 4,5,6 and 7 for nvgpu_posix_hweight16, nvgpu_posix_hweight32
* nvgpu_posix_hweight64, hweight32 and hweight_long.
*
* Output:
* The test returns PASS if all the hamming weight function invocations return
* the expected value. Otherwise the test returns FAIL.
*
*/
int test_hamming_weight(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_be32tocpu
*
* Description: Test the endian conversion implementation.
*
* Test Type: Feature
*
* Targets: be32_to_cpu
*
* Inputs: None
*
* Steps:
* 1) Invoke function be32_to_cpu with a fixed pattern as input.
* 2) Check if the machine is little endian.
* 3) If the machine is little endian, confirm that the return value from
* be32_to_cpu is equal to the little endian order of the pattern, else
* return FAIL.
* 3) EXPECT_BUG is also tested to make sure that BUG is not called where it is
* not expected.
*
* Output:
* The test returns PASS if BUG is called as expected based on the parameters
* passed and EXPECT_BUG handles it accordingly.
* The test returns FAIL if either BUG is not called as expected or if
* EXPECT_BUG indicates that a BUG call was made which was not requested by
* the test.
*
*/
int test_be32tocpu(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_minmax
*
* Description: Test the min and max implementations.
*
* Test Type: Feature
*
* Targets: min_t, min, min3, max
*
* Inputs: None
*
* Steps:
* 1) Invoke function min in loop with different input parameter values.
* 2) Check if the return value is the minimum value among the parameters
* passed. Else return FAIL.
* 3) Invoke function min3 in loop with different input parameter values.
* 4) Check if the return value is the minimum value among the parameters
* passed. Else return FAIL.
* 5) Invoke function min_t in loop with type and values as input parameters.
* 6) Check if the return value is the minimum value among the parameters
* passed for every iteration. Else return FAIL.
* 7) Invoke function max in loop.
* 8) Check if the return value is the maximum value among the parameters
* passed for every iteration. Else return FAIL.
* 9) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of min and max implementations
* returns the expected value. Otherwise, test returns FAIL.
*
*/
int test_minmax(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_arraysize
*
* Description: Test ARRAY_SIZE macro implementation.
*
* Test Type: Feature
*
* Targets: ARRAY_SIZE
*
* Inputs: None
*
* Steps:
* 1) Invoke macro ARRAY_SIZE with multiple arrays and confirm
* that the results are as expected. Otherwise, return FAIL.
* 4) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of ARRAY_SIZE macro returns
* the results as expected. Otherwise, the test returns FAIL.
*
*/
int test_arraysize(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_typecheck
*
* Description: Test type checking macros.
*
* Test Type: Feature
*
* Targets: IS_UNSIGNED_TYPE, IS_UNSIGNED_LONG_TYPE,
* IS_SIGNED_LONG_TYPE
*
* Inputs: None
*
* Steps:
* 1) Invoke macros IS_UNSIGNED_TYPE, IS_UNSIGNED_LONG_TYPE,
* IS_SIGNED_LONG_TYPE ARRAY_SIZE with multiple data types and confirm
* that the results are as expected. Otherwise, return FAIL.
* 2) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of type checking macros returns
* the results as expected. Otherwise, the test returns FAIL.
*
*/
int test_typecheck(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_align_macros
*
* Description: Test align macro implementations.
*
* Test Type: Feature
*
* Targets: ALIGN, ALIGN_MASK, PAGE_ALIGN
*
* Inputs: None
*
* Steps:
* 1) Invoke macros ALIGN, ALIGN_MASK and PAGE_ALIGN and confirm that the
* results are masked as expected. Otherwise, return FAIL.
* 2) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of various align macros
* returns the results as expected. Otherwise, the test returns FAIL.
*
*/
int test_align_macros(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_round_macros
*
* Description: Test rounding macro implementation.
*
* Test Type: Feature
*
* Targets: round_mask, round_up, round_down
*
* Inputs: None
*
* Steps:
* 1) Invoke macro round_mask in loop and confirm that the mask generated is
* as expected. Otherwise, return FAIL.
* 2) Invoke macros round_up and round_up in loop for various input values and
* confirm that the values are rounded off as expected. Otherwise, return
* FAIL.
* 3) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of round macros returns the
* results as expected. Otherwise, the test returns FAIL.
*
*/
int test_round_macros(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_write_once
*
* Description: Test WRITE_ONCE macro implementation.
*
* Test Type: Feature
*
* Targets: WRITE_ONCE
*
* Inputs: None
*
* Steps:
* 1) Invoke macro WRITE_ONCE in loop and confirm that the value is written
* into the variable as expected. Otherwise, return FAIL.
* 2) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of WRITE_ONCE macro writes the
* value into the variable. Otherwise, the test returns FAIL.
*
*/
int test_write_once(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_div_macros
*
* Description: Test various division macro implementations.
*
* Test Type: Feature
*
* Targets: DIV_ROUND_UP_U64, DIV_ROUND_UP, do_div, div64_u64
*
* Inputs: None
*
* Steps:
* 1) Invoke macros DIV_ROUND_UP_U64, DIV_ROUND_UP, do_div and div64_u64 and
* confirm that the results are as expected. Otherwise, return FAIL.
* 2) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of various division macros
* returns the results as expected. Otherwise, the test returns FAIL.
*
*/
int test_div_macros(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_containerof
*
* Description: Test container_of implementation.
*
* Test Type: Feature
*
* Targets: container_of
*
* Inputs: Global struct instance cont.
*
* Steps:
* 1) Invoke container_of with the first variable ptr in cont.
* 2) Invoke container_of with the second variable ptr in cont.
* 3) Confirm if both the invocation of container_of macro returns the address
* of the global struct instance cont. Otherwise, return FAIL.
* 4) Return PASS.
*
* Output:
* The test returns PASS if both the invocation of container_of returns the
* same address as that of the global struct instance cont. Otherwise, the test
* returns FAIL.
*
*/
int test_containerof(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for test_hertzconversion
*
* Description: Test hertz conversion macro implementation.
*
* Test Type: Feature
*
* Targets: HZ_TO_KHZ, HZ_TO_MHZ, HZ_TO_MHZ_ULL,
* KHZ_TO_HZ, MHZ_TO_KHZ, KHZ_TO_MHZ, MHZ_TO_HZ_ULL
*
* Inputs: None
*
* Steps:
* 1) Invoke various hertz conversion macros with different input values.
* 2) Check and confirm if the conversion macro results in expected value.
* Otherwise, return FAIL.
* 4) Return PASS.
*
* Output:
* The test returns PASS if all the invocations of various hertz conversion
* functions returns the results as expected. Otherwise, the test returns FAIL.
*
*/
int test_hertzconversion(struct unit_module *m, struct gk20a *g, void *args);
#endif /* __UNIT_POSIX_UTILS_H__ */