zephyr/lib/libc/minimal/include/stdlib.h
Yasushi SHOJI b2fde24c4c libc: minimal: Add rand() and srand()
rand() and srand() are pseudo-random number generator functions
defined in ISO C. This implementation uses the Linear Congruential
Generator (LCG) algorithm with the following parameters, which are the
same as used in GNU Libc "TYPE_0" algorithm.

  Modulus 2^31
  Multiplier 1103515245
  Increment 12345
  Output Bits 30..0

Note that the default algorithm used by GNU Libc is not TYPE_0, and
TYPE_0 should be selected first by an initstate() call as shown below.

All global variables in a C library must be routed to a memory
partition in order to be used by user-mode applications when
CONFIG_USERSPACE is enabled.  Thus, srand_seed is marked as
such. z_libc_partition is originally used by the Newlib C library but
it's generic enough to be used by either the minimal libc or the
newlib.

All other functions in the Minimal C library, however, don't require
global variables/states.  Unconditionally using z_libc_partition with
the minimal libc might be a problem for applications utilizing many
custom memory partitions on platforms with a limited number of MPU
regions (eg. Cortex M0/M3). This commit introduces a kconfig option
CONFIG_MINIMAL_LIBC_RAND so that applications can enable the
functions if needed.  The option is disabled by default.

Because this commit _does_ implement rand() and srand(), our coding
guideline check on GitHub Action finds it as a violation.

    Error: lib/libc/minimal/include/stdlib.h:45:WARNING: Violation to
    rule 21.2 (Should not used a reserved identifier) - srand

But this is false positive.

The following is a simple test program for LCG with GNU Libc.

  #include <stdio.h>
  #include <stdlib.h>

  int main()
  {
          static char state[8];

          /* Switch GLIBC to use LCG/TYPE_0 generator type. */
          initstate(0, state, sizeof(state));

          srand(1);  /* Or any other value. */
          printf("%d\n", rand());
          printf("%d\n", rand());

          return 0;
  }

See initstate(3p) for more detail about how to use LCG in GLIBC.

Signed-off-by: Yasushi SHOJI <yashi@spacecubics.com>
2021-07-20 13:32:36 -04:00

68 lines
1.3 KiB
C

/* stdlib.h */
/*
* Copyright (c) 2011-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_STDLIB_H_
#define ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_STDLIB_H_
#include <stddef.h>
#include <limits.h>
#ifdef __cplusplus
extern "C" {
#endif
unsigned long strtoul(const char *nptr, char **endptr, int base);
long strtol(const char *nptr, char **endptr, int base);
int atoi(const char *s);
void *malloc(size_t size);
void free(void *ptr);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void *reallocarray(void *ptr, size_t nmemb, size_t size);
void *bsearch(const void *key, const void *array,
size_t count, size_t size,
int (*cmp)(const void *key, const void *element));
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
void _exit(int status);
static inline void exit(int status)
{
_exit(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)
{
return (__n < 0) ? -__n : __n;
}
static inline long labs(long __n)
{
return (__n < 0L) ? -__n : __n;
}
static inline long long llabs(long long __n)
{
return (__n < 0LL) ? -__n : __n;
}
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_LIB_LIBC_MINIMAL_INCLUDE_STDLIB_H_ */