sys/newlib: Split stubs and make modules provide non-stubs#9258
sys/newlib: Split stubs and make modules provide non-stubs#9258jcarrano wants to merge 7 commits intoRIOT-OS:masterfrom
Conversation
dcd9d56 to
3b0b6be
Compare
Agreed
I like the idea of implementing these functions in a higher layer thant xxx_r functions, but tend to think these POSIX functions should be implemented on top of RIOT modules and not by the modules. See for instance here. If there are several modules implementing POSIX functions it could be really hard to configure properly. Otherwise, everything under sys/posix can be configured or arranged as wished. |
|
@jcarrano on second thoughts (and following the case of sock_t structs), I think the proposal you describe can do the trick. The only issue I could see (fixable though) is a way to prevent to modules implementing the same functions so we don't get duplicated symbols |
|
@jia200x Right now I don't think it's a problem because there is no overlapping functionality (we have one vfs, one xtimer, etc). Creating a separate module is a good proposal too for future proofing. We might see a proliferation of modules, though. |
|
As you say, I think it can solve the problem for some time. If at some point becomes a problem, we can fix it later :) |
|
I'm experimenting with a new C library, baselibc (see #10292 ), and having the newlib support split would help me quite a bit. baselibc does not replace newlib. It sits on top, replacing some of the functions. This means that some adaptors/stubs still need to be there, and some others need to be implemented for baselibc instead. Regarding this PR: I'm not 100% sure that implementing |
35dc792 to
1e972b4
Compare
kaspar030
left a comment
There was a problem hiding this comment.
I think the ordering needs rework. what's "stub_std_*" and why does it have to be in sys/?
Also I don't think that RIOT modules should provide libc functions just because they re related or can be based on them.
|
stub_std_* is a stub for the standard library. Part of the motivation for this change is to make the use aware when he is using stubs, instead of silently putting in a function that fails. I don't see any other place to put such a module than in sys.
Ok, so that means that I should split the |
Noone calls libc "the standard library" or "std".
If they're newlib stubs,
I'd say so. make it a submodule of newlib-syscall-default. put in sys/newlib-syscalls-default/clock_xtimer.c. |
Is "stdlib" better?
I want to avoid SUBMODULES. It is an unnecessary complication and there is really no need. If I use a regular module I just have to create a directory and a trivial Makefile and I'm done. Regarding PSEUDOMODULEs, they should only when they are needed, that is, when they enable or disable code that cannot be split apart. |
No, "stdlib" is ambiguous with
All is fine and well if you want to avoid submodules. Open an issue so we can discuss and change current best practices. Until then, use submodules. Why do you want to make "clock()" it's own module? |
Because that is what it is, a component, which can be depended upon and with dependencies to other modules. I can be taken in and out independently of other modules. Too many issues have arisen from not keeping the module system simple. |
It is also horribly inefficient. Distinct module gets it's own folder, Makefile, submake instance, ...
I tend to agree, but which that has relevance are you referring to? |
Only because of the current implementation. I'm against architecture our system around limitations that can be avoided (and will eventually be fixed). It just makes the problem worse. It's not a module per function, it's just that this one module happens to have one function. I try to avoid to avoid such subjective grouping based on what "seems" small. |
I was under the impression that there'll be multiple implementations for libc functions coming.
The need for a folder & Makefile & DIRS entry & Makefile.dep entry per module is a technical limitation that will eventually get fixed. Without that, you'd put clock_xtimer.c whereever it fits best and maybe mention it once in a proper build description file. Using submodules is a step towards fixing the modules system. Why again are submodules too complicated? |
1e972b4 to
2e7311a
Compare
Newlib's clock() depends on times() (which has to be supplied by the os). This patch add two new (sub)modules: - newlib_syscalls_riot_clock uses xtimer to provide for the clock() function. - newlib_stubs_clock provides a stub implementation for _times_r() in case xtimer is not available and a stub is acceptable. The new modules `newlib_syscalls_riot` and `newlib_stubs` are meant to contain the rest of the system calls that will be split from newlib_syscalls_default by groups. For ease of use, if xtimer is used, the newlib_syscalls_riot_clock is automatically included. This can be prevented by explicitly adding newlib_stubs_clock to USEMODULE. The test, tests/libc_time_h_relative, can be compiled with or without USEMODULE=newlib_stubs_clock to see the difference.
Add a new "time" submodule to newlib_syscalls_riot that implements the C standard library function "time()" using the RTC. A stub module "newlib_stubs_time" is also provided for those cases where an RTC is not present but some package requires time() in order to link properly. The prvious implementation in newlib_syscalls_default was buggy in that it provided CPU time. If periph_rtc is used, and newlib_stubs_time was not explicitly selected, then the newlib_syscalls_riot_time module will be used automatically. libc_time_h_absolute provides a test compile with: ``` USEMODULE=newlib_stubs_time BOARD=saml21-xpro make -C tests/libc_time_h_absolute all flash term ``` To use the stub and remove the USEMODULE thing to use the real rtc implemetation.
|
Following some discussions with @cladmi, I reorganized the module structure and changed the names. |
|
IMO, this could be massively simplified by just adding conditional compile time warnings to the stub implementations. No need to touch 19 files and multiply 40 lines by ten. I'm thinking Anyhow,
|
That is not the point. The point is to be able to choose the implementation, and to be able to provide a subset of the functionality. If you look at the MIPS UHI syscalls you will see some of the stuff is copy-pasted from newlib_syscalls_default. By being granular only some syscalls can be replaced. Also, I don't want to see a warning if I chose to use a stub, and I don't want an app to be built with stubs automatically, because a broken app should not even build. Only if the user decides that it is OK to have a stub for a certain functionality should the compilation proceed, and there is no point in reminding him with a warning of that he himself did. I think that handling conditional compilation/inclusion using the build system is superior to using pre-processor directives:
The If it needs to be removed then OK, but I would do that on another PR (and make this one depend on it).
I think I can come up with a self-testing, non interactive test. I don't think I can test the stubs in the unit tests with the rest of the stuff because it requires linking a conflicting set of symbols.
I'm not going with one function per line, only in these cases it happens to contain only one, and because they implement different, unrelated functionality with no interdependency, they are split. When I do process management and file system, there will be more than one function. The "clock" stub implements
|
The implementation of read/write/close, etc using VFS is moved to it's own submodule, newlib_syscalls_riot_vfs. The stubs for those functions (with the exception of read and write) now live in newlib_stubs_fs. The implementaion of read and write that maps every file to the UART is in newlib_syscalls_riot_serial_rw.
This allows to save space by not compiling in serial support, provided application do not check the exit status of IO functions. If a program checks the exit status, it will realize it is a stub, but such a program probably has REAL I/O as part of it's specification, and therefore it should not be using stubs in the same place.
some code in pkg claims to be written in C99, yet uses some POSIX functions.
Take sbrk() out of newlib_syscalls_default This should make it easier for BSP providers to change the implementation without having to edit newlib_syscalls_default or fiddle with preprocessor macros. TODO: figure out if it makes sense to provide a stub for this one.
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
Background
To get the full standard C library, newlib needs to be provided, at minimum, with the following basic calls (shown here in their reentrant versions):
File handling:
_open_r,_close_r,_lseek_r,_read_r,_write_r,_stat_r,_fstat_r,_link_r,_unlink_r,_fcntl_rProcess control:
_execve_r,_wait_r,_fork_r,_getpid_rMemory management:
_sbrk_rTimekeeping:
_gettimeofday_r,_times_rStubs for these functions can be found in the newlib source, under newlib/libc/reent/.
If these are provided, newlib will implement the rest of the standard functions directly or indirectly based on them. Some of the basic calls are not C but rather POSIX definition, which are generally more strict. For example POSIX's
times()is more detailed than C'sclock(). By default newlib implementsclock()usingtimes().There is also the possibility of implementing some higher level function. For example, an alternate definition of
clock()can be provided that does not usetimes(), or a version ofmalloc()that does not usesbrk().Problem
The current implementation of the above mentioned functions lives in sys/newlib_syscalls_default/syscalls.c. For filesystem functions (and _gettimeofday_r), functioning implementations are provided if VFS (or xtimer) is included, for other functions, there are only stubs. Also, some are missing (see #9051), and some incorrectly defined (see #9187)
The problem with stubs is that, while useful (sometimes we have external packages that depend on having C standard function available and it may be acceptable if these are stubs that always fail) they may turn a linker error into a runtime error. It would be desirable to let the user decide and make him explicitly request to have stubs compiled in.
Contribution
For a detailed explanation, see the commit messages.
I propose that the support for C standard functions is provided directly by whatever module can do it. In the first commit, I'm making xtimer provide clock(). In the next commit, I will make RTC provide for the "absolute time" functions (either _gettimeofday_r or time()).
The implementation for different types of functions (file handling, process control, etc) will be split into several modules to allow the user to decide for what parts of the API he wants stubs. Stub modules will be provided for the different categories.
New modules and submodules:
Testing
For the clock() implementation:
For time():
Issues/PRs references
This is a longer term and better solution than my previous PR: #9090
The package that is giving me headaches with the C api: #8847, #9153
If the stubs are split, implementing #10292 becomes easier and nicer.