mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 02:22:34 +03:00
Open source GPL/LGPL release
This commit is contained in:
26
userspace/units/posix/bitops/Makefile
Normal file
26
userspace/units/posix/bitops/Makefile
Normal 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
|
||||
35
userspace/units/posix/bitops/Makefile.interface.tmk
Normal file
35
userspace/units/posix/bitops/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/bitops/Makefile.tmk
Normal file
35
userspace/units/posix/bitops/Makefile.tmk
Normal 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:
|
||||
743
userspace/units/posix/bitops/posix-bitops.c
Normal file
743
userspace/units/posix/bitops/posix-bitops.c
Normal 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);
|
||||
432
userspace/units/posix/bitops/posix-bitops.h
Normal file
432
userspace/units/posix/bitops/posix-bitops.h
Normal 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 */
|
||||
26
userspace/units/posix/bug/Makefile
Normal file
26
userspace/units/posix/bug/Makefile
Normal 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
|
||||
35
userspace/units/posix/bug/Makefile.interface.tmk
Normal file
35
userspace/units/posix/bug/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/bug/Makefile.tmk
Normal file
35
userspace/units/posix/bug/Makefile.tmk
Normal 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:
|
||||
186
userspace/units/posix/bug/posix-bug.c
Normal file
186
userspace/units/posix/bug/posix-bug.c
Normal 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);
|
||||
119
userspace/units/posix/bug/posix-bug.h
Normal file
119
userspace/units/posix/bug/posix-bug.h
Normal 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__ */
|
||||
26
userspace/units/posix/circ_buf/Makefile
Normal file
26
userspace/units/posix/circ_buf/Makefile
Normal 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
|
||||
35
userspace/units/posix/circ_buf/Makefile.interface.tmk
Normal file
35
userspace/units/posix/circ_buf/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/circ_buf/Makefile.tmk
Normal file
35
userspace/units/posix/circ_buf/Makefile.tmk
Normal 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:
|
||||
95
userspace/units/posix/circ_buf/posix-circbuf.c
Normal file
95
userspace/units/posix/circ_buf/posix-circbuf.c
Normal 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);
|
||||
88
userspace/units/posix/circ_buf/posix-circbuf.h
Normal file
88
userspace/units/posix/circ_buf/posix-circbuf.h
Normal 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 */
|
||||
26
userspace/units/posix/cond/Makefile
Normal file
26
userspace/units/posix/cond/Makefile
Normal 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
|
||||
35
userspace/units/posix/cond/Makefile.interface.tmk
Normal file
35
userspace/units/posix/cond/Makefile.interface.tmk
Normal 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:
|
||||
39
userspace/units/posix/cond/Makefile.tmk
Normal file
39
userspace/units/posix/cond/Makefile.tmk
Normal 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:
|
||||
552
userspace/units/posix/cond/posix-cond.c
Normal file
552
userspace/units/posix/cond/posix-cond.c
Normal 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);
|
||||
259
userspace/units/posix/cond/posix-cond.h
Normal file
259
userspace/units/posix/cond/posix-cond.h
Normal 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
26
userspace/units/posix/env/Makefile
vendored
Normal 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
|
||||
35
userspace/units/posix/env/Makefile.interface.tmk
vendored
Normal file
35
userspace/units/posix/env/Makefile.interface.tmk
vendored
Normal 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
35
userspace/units/posix/env/Makefile.tmk
vendored
Normal 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
229
userspace/units/posix/env/posix-env.c
vendored
Normal 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);
|
||||
28
userspace/units/posix/fault-injection/Makefile
Normal file
28
userspace/units/posix/fault-injection/Makefile
Normal 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
|
||||
35
userspace/units/posix/fault-injection/Makefile.interface.tmk
Normal file
35
userspace/units/posix/fault-injection/Makefile.interface.tmk
Normal 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:
|
||||
38
userspace/units/posix/fault-injection/Makefile.tmk
Normal file
38
userspace/units/posix/fault-injection/Makefile.tmk
Normal 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:
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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);
|
||||
@@ -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 */
|
||||
26
userspace/units/posix/kmem/Makefile
Normal file
26
userspace/units/posix/kmem/Makefile
Normal 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
|
||||
35
userspace/units/posix/kmem/Makefile.interface.tmk
Normal file
35
userspace/units/posix/kmem/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/kmem/Makefile.tmk
Normal file
35
userspace/units/posix/kmem/Makefile.tmk
Normal 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:
|
||||
257
userspace/units/posix/kmem/posix-kmem.c
Normal file
257
userspace/units/posix/kmem/posix-kmem.c
Normal 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);
|
||||
258
userspace/units/posix/kmem/posix-kmem.h
Normal file
258
userspace/units/posix/kmem/posix-kmem.h
Normal 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__ */
|
||||
26
userspace/units/posix/log2/Makefile
Normal file
26
userspace/units/posix/log2/Makefile
Normal 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
|
||||
35
userspace/units/posix/log2/Makefile.interface.tmk
Normal file
35
userspace/units/posix/log2/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/log2/Makefile.tmk
Normal file
35
userspace/units/posix/log2/Makefile.tmk
Normal 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:
|
||||
169
userspace/units/posix/log2/posix-log2.c
Normal file
169
userspace/units/posix/log2/posix-log2.c
Normal 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);
|
||||
147
userspace/units/posix/log2/posix-log2.h
Normal file
147
userspace/units/posix/log2/posix-log2.h
Normal 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 */
|
||||
26
userspace/units/posix/os_sched/Makefile
Normal file
26
userspace/units/posix/os_sched/Makefile
Normal 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
|
||||
35
userspace/units/posix/os_sched/Makefile.interface.tmk
Normal file
35
userspace/units/posix/os_sched/Makefile.interface.tmk
Normal 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:
|
||||
39
userspace/units/posix/os_sched/Makefile.tmk
Normal file
39
userspace/units/posix/os_sched/Makefile.tmk
Normal 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:
|
||||
81
userspace/units/posix/os_sched/posix-ossched.c
Normal file
81
userspace/units/posix/os_sched/posix-ossched.c
Normal 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);
|
||||
109
userspace/units/posix/os_sched/posix-ossched.h
Normal file
109
userspace/units/posix/os_sched/posix-ossched.h
Normal 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__ */
|
||||
26
userspace/units/posix/queue/Makefile
Normal file
26
userspace/units/posix/queue/Makefile
Normal 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
|
||||
35
userspace/units/posix/queue/Makefile.interface.tmk
Normal file
35
userspace/units/posix/queue/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/queue/Makefile.tmk
Normal file
35
userspace/units/posix/queue/Makefile.tmk
Normal 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:
|
||||
284
userspace/units/posix/queue/posix-queue.c
Normal file
284
userspace/units/posix/queue/posix-queue.c
Normal 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);
|
||||
154
userspace/units/posix/queue/posix-queue.h
Normal file
154
userspace/units/posix/queue/posix-queue.h
Normal 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__ */
|
||||
/*
|
||||
* @}
|
||||
*/
|
||||
26
userspace/units/posix/rwsem/Makefile
Normal file
26
userspace/units/posix/rwsem/Makefile
Normal 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
|
||||
35
userspace/units/posix/rwsem/Makefile.interface.tmk
Normal file
35
userspace/units/posix/rwsem/Makefile.interface.tmk
Normal 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:
|
||||
39
userspace/units/posix/rwsem/Makefile.tmk
Normal file
39
userspace/units/posix/rwsem/Makefile.tmk
Normal 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:
|
||||
300
userspace/units/posix/rwsem/posix-rwsem.c
Normal file
300
userspace/units/posix/rwsem/posix-rwsem.c
Normal 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);
|
||||
233
userspace/units/posix/rwsem/posix-rwsem.h
Normal file
233
userspace/units/posix/rwsem/posix-rwsem.h
Normal 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__ */
|
||||
26
userspace/units/posix/sizes/Makefile
Normal file
26
userspace/units/posix/sizes/Makefile
Normal 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
|
||||
35
userspace/units/posix/sizes/Makefile.interface.tmk
Normal file
35
userspace/units/posix/sizes/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/sizes/Makefile.tmk
Normal file
35
userspace/units/posix/sizes/Makefile.tmk
Normal 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:
|
||||
96
userspace/units/posix/sizes/posix-sizes.c
Normal file
96
userspace/units/posix/sizes/posix-sizes.c
Normal 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);
|
||||
71
userspace/units/posix/sizes/posix-sizes.h
Normal file
71
userspace/units/posix/sizes/posix-sizes.h
Normal 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__ */
|
||||
26
userspace/units/posix/thread/Makefile
Normal file
26
userspace/units/posix/thread/Makefile
Normal 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
|
||||
35
userspace/units/posix/thread/Makefile.interface.tmk
Normal file
35
userspace/units/posix/thread/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/thread/Makefile.tmk
Normal file
35
userspace/units/posix/thread/Makefile.tmk
Normal 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:
|
||||
309
userspace/units/posix/thread/posix-thread.c
Normal file
309
userspace/units/posix/thread/posix-thread.c
Normal 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(¶m, 0, sizeof(struct sched_param));
|
||||
|
||||
data = (struct unit_test_thread_data *)args;
|
||||
|
||||
if (data->check_priority) {
|
||||
pthread_getschedparam(pthread_self(), &policy, ¶m);
|
||||
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);
|
||||
127
userspace/units/posix/thread/posix-thread.h
Normal file
127
userspace/units/posix/thread/posix-thread.h
Normal 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__ */
|
||||
26
userspace/units/posix/timers/Makefile
Normal file
26
userspace/units/posix/timers/Makefile
Normal 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
|
||||
35
userspace/units/posix/timers/Makefile.interface.tmk
Normal file
35
userspace/units/posix/timers/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/timers/Makefile.tmk
Normal file
35
userspace/units/posix/timers/Makefile.tmk
Normal 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:
|
||||
419
userspace/units/posix/timers/posix-timers.c
Normal file
419
userspace/units/posix/timers/posix-timers.c
Normal 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);
|
||||
313
userspace/units/posix/timers/posix-timers.h
Normal file
313
userspace/units/posix/timers/posix-timers.h
Normal 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__ */
|
||||
26
userspace/units/posix/utils/Makefile
Normal file
26
userspace/units/posix/utils/Makefile
Normal 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
|
||||
35
userspace/units/posix/utils/Makefile.interface.tmk
Normal file
35
userspace/units/posix/utils/Makefile.interface.tmk
Normal 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:
|
||||
35
userspace/units/posix/utils/Makefile.tmk
Normal file
35
userspace/units/posix/utils/Makefile.tmk
Normal 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:
|
||||
628
userspace/units/posix/utils/posix-utils.c
Normal file
628
userspace/units/posix/utils/posix-utils.c
Normal 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);
|
||||
326
userspace/units/posix/utils/posix-utils.h
Normal file
326
userspace/units/posix/utils/posix-utils.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user