Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/guides/portability/posix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ This is implemented as part of the minimal C library available in Zephyr.
setlocale(),
snprintf(),+
sprintf(),+
srand(),
srand(),+
sscanf(),
strcat(),+
strchr(),+
Expand Down
2 changes: 1 addition & 1 deletion doc/guides/porting/arch.rst
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ details:

Some architectures may need to update software memory management structures
or modify hardware registers on another CPU when memory domain APIs are invoked.
If so, CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API must be selected by the
If so, :kconfig:`CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API` must be selected by the
architecture and some additional APIs must be implemented. This is common
on MMU systems and uncommon on MPU systems:

Expand Down
11 changes: 6 additions & 5 deletions doc/reference/kernel/other/interrupts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -377,10 +377,10 @@ argument is ignored.

Vector Table
------------
A vector table is generated when CONFIG_GEN_IRQ_VECTOR_TABLE is enabled. This
data structure is used natively by the CPU and is simply an array of function
pointers, where each element n corresponds to the IRQ handler for IRQ line n,
and the function pointers are:
A vector table is generated when :kconfig:`CONFIG_GEN_IRQ_VECTOR_TABLE` is
enabled. This data structure is used natively by the CPU and is simply an
array of function pointers, where each element n corresponds to the IRQ handler
for IRQ line n, and the function pointers are:

#. For 'direct' interrupts declared with :c:macro:`IRQ_DIRECT_CONNECT`, the
handler function will be placed here.
Expand All @@ -394,7 +394,8 @@ and the function pointers are:

Some architectures (such as the Nios II internal interrupt controller) have a
common entry point for all interrupts and do not support a vector table, in
which case the CONFIG_GEN_IRQ_VECTOR_TABLE option should be disabled.
which case the :kconfig:`CONFIG_GEN_IRQ_VECTOR_TABLE` option should be
disabled.

Some architectures may reserve some initial vectors for system exceptions
and declare this in a table elsewhere, in which case
Expand Down
4 changes: 2 additions & 2 deletions doc/reference/kernel/threads/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -485,8 +485,8 @@ The following code illustrates the ways a thread can terminate.
/* thread terminates at end of entry point function */
}

If CONFIG_USERSPACE is enabled, aborting a thread will additionally mark the
thread and stack objects as uninitialized so that they may be re-used.
If :kconfig:`CONFIG_USERSPACE` is enabled, aborting a thread will additionally
mark the thread and stack objects as uninitialized so that they may be re-used.

Runtime Statistics
******************
Expand Down
11 changes: 6 additions & 5 deletions doc/reference/usermode/memory_domain.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ Hardware Stack Overflow
``CONFIG_HW_STACK_PROTECTION`` is an optional feature which detects stack
buffer overflows when the system is running in supervisor mode. This
catches issues when the entire stack buffer has overflowed, and not
individual stack frames, use compiler-assisted CONFIG_STACK_CANARIES for that.
individual stack frames, use compiler-assisted :kconfig:`CONFIG_STACK_CANARIES`
for that.

Like any crash in supervisor mode, no guarantees can be made about the overall
health of the system after a supervisor mode stack overflow, and any instances
Expand Down Expand Up @@ -199,7 +200,7 @@ automatically.
Manual Memory Partitions
------------------------

The following code declares a global array buf, and then declares
The following code declares a global array ``buf``, and then declares
a read-write partition for it which may be added to a domain:

.. code-block:: c
Expand Down Expand Up @@ -254,7 +255,7 @@ BSS.
*/
K_APP_BMEM(my_partition) int var2;

The build system will ensure that the base address of my_partition will
The build system will ensure that the base address of ``my_partition`` will
be properly aligned, and the total size of the region conforms to the memory
management hardware requirements, adding padding if necessary.

Expand Down Expand Up @@ -301,8 +302,8 @@ There are a few memory partitions which are pre-defined by the system:
to specific memory domains.

- ``z_libc_partition`` - Contains globals required by the C library and runtime.
Required if using newlib. Required if using minimal libc with
``CONFIG_STACK_CANARIES`` enabled.
Required when using either the Minimal C library or the Newlib C Library.
Required when option:`CONFIG_STACK_CANARIES` is enabled.

Library-specific partitions are listed in ``include/app_memory/partitions.h``.
For example, to use the MBEDTLS library from user mode, the
Expand Down
13 changes: 8 additions & 5 deletions include/sys/libc-hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,14 @@ extern struct k_mem_partition z_malloc_partition;

#if defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_STACK_CANARIES) || \
defined(CONFIG_NEED_LIBC_MEM_PARTITION)
/* Minimal libc has no globals. We do put the stack canary global in the
* libc partition since it is not worth placing in a partition of its own.
*
* Some architectures require a global pointer for thread local storage,
* which is placed inside the libc partition.
/* - All newlib globals will be placed into z_libc_partition.
* - Minimal C library globals, if any, will be placed into
* z_libc_partition.
* - Stack canary globals will be placed into z_libc_partition since
* it is not worth placing in its own partition.
* - Some architectures may place the global pointer to the thread local
* storage in z_libc_partition since it is not worth placing in its
* own partition.
*/
#define Z_LIBC_PARTITION_EXISTS 1

Expand Down
13 changes: 13 additions & 0 deletions lib/libc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ config MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE
Enable smaller but potentially slower implementations of memcpy and
memset. On the Cortex-M0+ this reduces the total code size by 120 bytes.

config MINIMAL_LIBC_RAND
bool "Enables rand and srand functions"
select NEED_LIBC_MEM_PARTITION
help
Enable rand() and srand() for the minimal libc. The
functions implicitly access global/static data. Such data
must be put into a memory partition if CONFIG_USERSPACE=y,
and disabling this option may save an entry for application
defining many custom partitions.

Say 'Y' here if you need rand() and srand(). This might require
an additional memory partition.

endif # MINIMAL_LIBC

config STDOUT_CONSOLE
Expand Down
1 change: 1 addition & 0 deletions lib/libc/minimal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ zephyr_library_sources(
)

zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK source/time/time.c)
zephyr_library_sources_ifdef(CONFIG_MINIMAL_LIBC_RAND source/stdlib/rand.c)
6 changes: 6 additions & 0 deletions lib/libc/minimal/include/stdlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#define ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_STDLIB_H_

#include <stddef.h>
#include <limits.h>

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -37,7 +39,11 @@ static inline void exit(int status)
}
void abort(void);

#ifdef CONFIG_MINIMAL_LIBC_RAND
#define RAND_MAX INT_MAX
int rand(void);
void srand(unsigned int seed);
#endif /* CONFIG_MINIMAL_LIBC_RAND */

static inline int abs(int __n)
{
Expand Down
29 changes: 29 additions & 0 deletions lib/libc/minimal/source/stdlib/rand.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2021 Space Cubics, LLC.
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdlib.h>
#include <sys/libc-hooks.h>
#include <app_memory/app_memdomain.h>

#define LIBC_DATA K_APP_DMEM(z_libc_partition)

#define OUTPUT_BITS (0x7fffffffU)
#define MULTIPLIER (1103515245U)
#define INCREMENT (12345U)

static LIBC_DATA unsigned long srand_seed = 1;

void srand(unsigned int s)
{
srand_seed = s;
}

int rand(void)
{
srand_seed = (MULTIPLIER * srand_seed + INCREMENT) & OUTPUT_BITS;

return srand_seed;
}
1 change: 1 addition & 0 deletions tests/crypto/mbedtls/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ CONFIG_MBEDTLS_CFG_FILE="config-tls-generic.h"
CONFIG_MBEDTLS_TEST=y
CONFIG_ZTEST=y
CONFIG_TEST_USERSPACE=y
CONFIG_MINIMAL_LIBC_RAND=y
14 changes: 0 additions & 14 deletions tests/crypto/mbedtls/src/mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,6 @@
#include "mbedtls/memory_buffer_alloc.h"
#endif

#if defined(MBEDTLS_RSA_C)
int rand(void)
{
static ZTEST_DMEM uint32_t seed = 7U;

seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;

return seed;
}

#endif

static int test_snprintf(size_t n, const char ref_buf[10], int ref_ret)
{
int ret;
Expand Down
1 change: 1 addition & 0 deletions tests/lib/c_lib/prj.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
CONFIG_ZTEST=y
CONFIG_TEST_USERSPACE=y
CONFIG_ZTEST_FATAL_HOOK=y
CONFIG_MINIMAL_LIBC_RAND=y
109 changes: 109 additions & 0 deletions tests/lib/c_lib/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,112 @@ void test_time(void)
zassert_not_null(gmtime_r(&tests4, &tp), "gmtime_r failed");
}

/**
*
* @brief Test rand function
*
*/
void test_rand(void)
{
int a;

a = rand();
/* The default seed is 1 */
zassert_equal(a, 1103527590, "rand failed");
}

/**
*
* @brief Test srand function
*
*/
void test_srand(void)
{
int a;

srand(0);
a = rand();
zassert_equal(a, 12345, "srand with seed 0 failed");

srand(1);
a = rand();
zassert_equal(a, 1103527590, "srand with seed 1 failed");

srand(10);
a = rand();
zassert_equal(a, 297746555, "srand with seed 10 failed");

srand(UINT_MAX - 1);
a = rand();
zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed");

srand(UINT_MAX);
a = rand();
zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed");
}

/**
*
* @brief Test rand function for reproducibility
*
*/
void test_rand_reproducibility(void)
{
int a;
int b;
int c;

srand(0);
a = rand();
zassert_equal(a, 12345, "srand with seed 0 failed");
srand(0);
b = rand();
zassert_equal(b, 12345, "srand with seed 0 failed (2nd)");
srand(0);
c = rand();
zassert_equal(c, 12345, "srand with seed 0 failed (3rd)");

srand(1);
a = rand();
zassert_equal(a, 1103527590, "srand with seed 1 failed");
srand(1);
b = rand();
zassert_equal(b, 1103527590, "srand with seed 1 failed (2nd)");
srand(1);
c = rand();
zassert_equal(c, 1103527590, "srand with seed 1 failed (3rd)");

srand(10);
a = rand();
zassert_equal(a, 297746555, "srand with seed 10 failed");
srand(10);
b = rand();
zassert_equal(b, 297746555, "srand with seed 10 failed (2nd)");
srand(10);
c = rand();
zassert_equal(c, 297746555, "srand with seed 10 failed (3rd)");

srand(UINT_MAX - 1);
a = rand();
zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed");
srand(UINT_MAX - 1);
b = rand();
zassert_equal(b, 2087949151, "srand with seed UINT_MAX - 1 failed (2nd)");
srand(UINT_MAX - 1);
c = rand();
zassert_equal(c, 2087949151, "srand with seed UINT_MAX - 1 failed (3rd)");

srand(UINT_MAX);
a = rand();
zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed");
srand(UINT_MAX);
b = rand();
zassert_equal(b, 1043980748, "srand with seed UINT_MAX failed (2nd)");
srand(UINT_MAX);
c = rand();
zassert_equal(c, 1043980748, "srand with seed UINT_MAX failed (3rd)");
}

/**
*
* @brief test abort functions
Expand Down Expand Up @@ -966,6 +1072,9 @@ void test_main(void)
ztest_unit_test(test_memcpy),
ztest_unit_test(test_memmove),
ztest_unit_test(test_time),
ztest_unit_test(test_rand),
ztest_unit_test(test_srand),
ztest_unit_test(test_rand_reproducibility),
ztest_unit_test(test_abort),
ztest_unit_test(test_exit),
ztest_unit_test(test_str_operate),
Expand Down