-
Notifications
You must be signed in to change notification settings - Fork 8.2k
libc/minimal: Add rand and srand #32667
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Or should I call |
|
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
|
@enjiamai, @KangJianX would mind to give me some feedback? |
|
Hi @yashi , OK, please give me some time to take look at this, I'll feedback to you later. thanks! |
|
Hi @yashi , I have no problem with this implementation, it looks good, and I think we need this. I would so appreciate it if some basic test cases for this can also be added to tests/lib/c_lib/src/. How do you think? thank you! |
enjiamai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please help to add the test cases for these, thank you!
enjiamai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great~ no problem from my side, thanks!
32fe35b to
d05db7b
Compare
pfalcon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm always +1 for sustainably growing the minimal library. But IMHO there're few cleanups to be done and questions to be answered before this is ready for inclusion.
Another note - we usually try to put tests into a separate commit vs the core changes.
|
I also find the current commit message to be confusing: You don't implement initstate(), so why people should see its man? I however followed the advice and what I see is: In other words, rand/srand vs random/initstate seems to be two parallel, independent pseudo-random number generation function sets. You here don't implement the latter, so references to initstate() should rather be removed. Likewise, please double-check that rand/srand implementation matches that of glibc. If it is, please update the sample in the commit message to use rand/srand. And if it's not, I'd suggest to just use the sample implementation from POSIX: https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand.html and remove references to glibc. (And if there's some confusion on my side, please let me know what I'm missing.) |
|
In order to test the Linear congruential generator algorithm, which is refered as I've updated my commit log as below for more clarity.
|
That's an interesting implementation detail of GLIBC, but I don't see how that relates to the functions srand()/rand() which are being implemented here. Nothing in https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand.html mentions initstate(). Nor you implement initstate(). So, why do you mention it at all? Let's start from the beginning. Do you want Zephyr's implementation of srand()/rand() to have the same behavior/produce the same values as Glibc's srand()/rand()? If so, I'm generally +1 for that, as Glibc is a well known library and I'm for being consistent with well-know de-facto standard. But then please sure that you exactly follow behavior of srand()/rand() and don't involve unrelated implementation details, like the fact that in Glibc, srand() is implemented in terms of initstats(). And well, if you don't have that specific requirement to follow Glibc behavior, just use the simple algorithm from "Generating the Same Sequence on Different Machines" subheading of https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand.html .
That page still described the functions: And not srand()/rand(). |
|
@pfalcon, thanks for your feedback. The reason why I've chosen GLIBC LCG is that I assumed most of the developers in the Zephyr community prefer to have the same algorithm as their development environment, which is, I also assume, Linux with GLIBC. I don't have any preferences at all. And the reason I put the reference in the commit log is that when someone wants to verify my implementation, it'd be nice to give a point or two for them. I thought it'd be helpful for future references. Nothing else. I followed GLIBC LCG's behavior in the Zephyr implementation. No detail, nor Again, I don't have any preferences in the algorithms. I just want |
a1411ec to
291b848
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this include really needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nop. I'll leave stdlib.h there for checking the rand() and srand() declarations against the definitions.
|
@stephanosio, I saw the MAINTAINERS.yml change and you are now the maintainer of libcs. Would you mind reviewing this PR? I just rebased to the main. Thanks. |
|
@yashi - can you please address any remaining comments? |
|
Yes. Will do it in this weekend. |
d600da5 to
aa471fd
Compare
stephanosio
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some additional comments
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 <[email protected]>
When MBEDTLS_RSA_C is defined, mbedtls define its local version of rand() function. Since we already have rand() in our minimal libc, we can safely remove this. Signed-off-by: Yasushi SHOJI <[email protected]>
- simple tests for each function - a reproducibility test for rand with the same seed values Signed-off-by: Yasushi SHOJI <[email protected]>
Under the "OS Abstraction / POSIX Support" section in the "User and Developer Guides", we somehow had rand() function already listed and marked supported, but not srand(). Add srand() to the list. Signed-off-by: Yasushi SHOJI <[email protected]>
Some Kconfig options are left marked as inline literals. But in Zephyr document, we use the "kconfig" role provided by Sphinx. Signed-off-by: Yasushi SHOJI <[email protected]>
Mark variables up if used in plain sentences for easier reading. Signed-off-by: Yasushi SHOJI <[email protected]>
The global variables in the Minimal C library are now placed in z_libc_partition, update the document accordingly. Signed-off-by: Yasushi SHOJI <[email protected]>
|
fixes #6493 |
stephanosio
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
rand() and srand() are pseudo-random number generator functions
defined in ISO C. This implementation uses the Linear congruential
generator algorithm with the following parameters, which are the same
as GNU Libc.
Modulus 0x7fffffff
Multiplier 1103515245
Increment 12345
ISO C / POSIX.1-2001 uses bits high 15 bits for Modulus, thus RAND_MAX
32767. ref rand(3).
Signed-off-by: Yasushi SHOJI [email protected]