Skip to content
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

cpu/native: make use of stdio_read() / stdio_write() #16822

Merged
merged 1 commit into from
Sep 22, 2021

Conversation

benpicco
Copy link
Contributor

@benpicco benpicco commented Sep 7, 2021

Contribution description

On native the functions stdio_read() / stdio_write() were not used.
Those functions are intended for alternative stdio implementations.
As a result, no alternative stdio could be used on native.

To fix this, call the functions in _native_read() / _native_write() when dealing with stdio fds.

Testing procedure

native applications should work as before.
But now alternative stdio implementations are possible.

Issues/PRs references

needed for #16723 to work on native

@github-actions github-actions bot added Area: cpu Area: CPU/MCU ports Platform: native Platform: This PR/issue effects the native platform labels Sep 7, 2021
@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Sep 7, 2021
@benpicco
Copy link
Contributor Author

benpicco commented Sep 8, 2021

Ok turns out guarding the read / write with _native_syscall_enter()/_native_syscall_leave() breaks tests/sys_atomic_utils

@benpicco benpicco requested review from miri64, kaspar030, LudwigKnuepfer and maribu and removed request for miri64 September 8, 2021 13:36
Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. Some comments inline.

cpu/native/stdio_native/stdio_native.c Outdated Show resolved Hide resolved
cpu/native/stdio_native/stdio_native.c Outdated Show resolved Hide resolved
cpu/native/syscalls.c Outdated Show resolved Hide resolved
@kfessel
Copy link
Contributor

kfessel commented Sep 17, 2021

I had some hope this would help with #16834 but it does not.
i tried to readd the native_syscall_enter and leave but that did not help either

Copy link
Contributor

@kfessel kfessel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing STDERR, which i assume should be handled similar to STDOUT.

Having a deeper look it i think:
the whole printf and getchar system seems to avoid going through riots VFS making them kind of disconnected from each other.

  • Shouldn't _native_write call vfs.write?

Maybe someone with a better insight into this VFS (e.g.: @kaspar030) can comment on that.

@miri64
Copy link
Member

miri64 commented Sep 20, 2021

the whole printf and getchar system seems to avoid going through riots VFS making them kind of disconnected from each other.

That's somewhat the point, as vfs is supposed to be optional (you do not always want to have a file system). Please let's keep that as is. We do not want make file systems accidentally mandatory and then have a no-op filesystem in case we do not have one, like we currently have with stdio (see stdio_null).

@benpicco
Copy link
Contributor Author

This is missing STDERR, which i assume should be handled similar to STDOUT.

I was thinking of that as a feature, but you are right that it's more consistent that way, fixed.

@kaspar030
Copy link
Contributor

* Shouldn't _native_write call vfs.write?

Maybe someone with a better insight into this VFS (e.g.: @kaspar030) can comment on that.

The issue is that read() etc. are blocking syscalls, even when used as _native_read() etc.
The solution would be to port this to use async io. There's already native_async_read() etc. in place and used by other modules.

Copy link
Contributor

@kfessel kfessel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With comments by miri64 and kaspar030, i think the non-blocking read is out of scope for this PR. I tried something with async_read in stdio_native and this patch helped in doing so.

This PR also changes how stdio works into the form someone reading the directory structure in native would expect it to do.

Lets avoid the scope creep. 🚀

Comment on lines 253 to 254
ssize_t res = stdio_write(iov->iov_base, iov->iov_len);
iov++;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think res needs to be compared to iov->iov_len before advancing to next element,
(there are stdio implementations in RIOT that might not write everything given to them (avoid blocking))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2402326 should fix this

(Is this function actually ever used in RIOT?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Is this function actually ever used in RIOT?)

afaik there is/was something in glibc that uses it for something more common

ssize_t res = stdio_write((void *)((uintptr_t)iov->iov_base + offset),
iov->iov_len - offset);
if (res < 0) {
return res;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return res;
if (r > 0 )return r; else return res;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that how writev is supposed to behave oO?

Copy link
Contributor

@kfessel kfessel Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manpage says:

On success, readv(), preadv(), and preadv2() return the number of bytes read;\
 writev(), pwritev(), and pwritev2() return the number of bytes written.

       Note that it is not an error for a successful call to transfer fewer bytes than\
 requested (see read(2) and write(2))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spec is a bit different though.

Copy link
Contributor

@kfessel kfessel Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about that since the the spec says return bytes written on success, which it does not defined by it, but the manpage does so, as any byte written is a success.

On the other hand the specs define the unsuccess (error) as the fd is not changed -> nothing is written?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rephrase... not really sure what you mean.

Copy link
Contributor

@kfessel kfessel Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the spec says:

Upon successful completion, writev() shall return the number of bytes actually written.

but it does not define success,
but it defines the unsuccess (error) case

 Otherwise, it shall return a value of -1, the file-pointer shall remain unchanged,\
 and errno shall be set to indicate an error.

this says the the file-pointer shall remain unchanged on error i am not sure if there is a file-point file/char-device content equality but if there is this means the nothing has to be written if -1 if returned.

the manpage on the other hand defines the success as a partial write

Note that it is not an error for a successful call to transfer fewer bytes than requested

Copy link
Contributor

@kfessel kfessel Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the write manpage (advertised by the writev page) goes into detail howto get the error state:

In  the  event  of  a  partial write, the caller can make another write()\
 call to transfer the remaining bytes. \
The subsequent call will either transfer further bytes or may result \
 in an error (e.g., if the disk is now full)

Comment on lines 253 to 262
size_t offset = 0;
while (iov->iov_len > offset) {
ssize_t res = stdio_write((void *)((uintptr_t)iov->iov_base + offset),
iov->iov_len - offset);
if (res < 0) {
return res;
}
offset += res;
}
r += offset;
Copy link
Contributor

@kfessel kfessel Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would avoid the inner loop: (return on the first write that is less than it was asked to the app would be expected to repead the write as it is written in the manpage)

Suggested change
size_t offset = 0;
while (iov->iov_len > offset) {
ssize_t res = stdio_write((void *)((uintptr_t)iov->iov_base + offset),
iov->iov_len - offset);
if (res < 0) {
return res;
}
offset += res;
}
r += offset;
ssize_t res = stdio_write((void *)((uintptr_t)iov->iov_base),
iov->iov_len);
if( res >= 0 ){
r += res;
}
if (res < iov->iov_len) {
return (r>=0) ? r : res;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, changed it - this is a strange API

@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Sep 22, 2021
cpu/native/syscalls.c Outdated Show resolved Hide resolved
Copy link
Contributor

@kfessel kfessel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR also changes how stdio works into the form someone reading the directory structure in native would expect it to do.

I tried something with async_read in stdio_native and this patch helped to do so.

@kfessel
Copy link
Contributor

kfessel commented Sep 22, 2021

please squash

On `native` the functions stdio_read() / stdio_write() were not
used.
Those functions are intended for alternative stdio implementations.
As a result, no alternative stdio could be used on `native`.

To fix this, call the functions in `_native_read()` / `_native_write()`
when dealing with stdio fds.
@benpicco benpicco merged commit cc3df3e into RIOT-OS:master Sep 22, 2021
@benpicco benpicco deleted the cpu/native-stdio branch September 22, 2021 18:47
@benpicco benpicco added this to the Release 2021.10 milestone Oct 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: native Platform: This PR/issue effects the native platform
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants