Skip to content

Commit

Permalink
lib: os: fdtable: Add syscalls for POSIX read/write/close operations
Browse files Browse the repository at this point in the history
Fdtable is a kernel-level structure, so functions accessing it, like
read(), write(), close(), should be syscalls. This conversion however
emphasizes a difference between "syscall" and "C standard library
function". C stdlib functions should be represented by just a
standard linkage symbol, and can be used even without prototype.
Syscall is however a special code sequence, which may require special
attributes and thus a prototype for usage. To deal with these
distinction, we define a convention that "sys_name" is a syscall,
while "name" is a normal C function (implemented as a wrapper around
syscall). (And we also need to define "_name" to interface with Newlib
(actually, just "_write".))

Fixes: zephyrproject-rtos#25407

Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
  • Loading branch information
pfalcon committed Jun 11, 2020
1 parent 7f9b85e commit c2bc3fd
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 4 deletions.
14 changes: 13 additions & 1 deletion include/posix/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,15 @@ extern "C" {
#endif

#ifdef CONFIG_POSIX_API
/* File related operations */
/* File related operations. Convention: "sys_name" is a syscall (needs
* prototype in this file for usage). "name" is a normal userspace
* function (implemented as a wrapper for syscall), usable even
* without prototype, per classical C handling. This distinction
* is however implemented on demand, based on the actual usecases seen.
*/
__syscall int sys_close(int file);
__syscall ssize_t sys_write(int file, const void *buffer, size_t count);
__syscall ssize_t sys_read(int file, void *buffer, size_t count);
extern int close(int file);
extern ssize_t write(int file, const void *buffer, size_t count);
extern ssize_t read(int file, void *buffer, size_t count);
Expand Down Expand Up @@ -50,4 +58,8 @@ int usleep(useconds_t useconds);
}
#endif

#ifndef CONFIG_ARCH_POSIX
#include <syscalls/unistd.h>
#endif /* CONFIG_ARCH_POSIX */

#endif /* ZEPHYR_INCLUDE_POSIX_UNISTD_H_ */
61 changes: 58 additions & 3 deletions lib/os/fdtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <kernel.h>
#include <sys/fdtable.h>
#include <sys/speculation.h>
#ifdef CONFIG_POSIX_API
#include <posix/unistd.h>
#endif
#include <syscall_handler.h>

struct fd_entry {
Expand Down Expand Up @@ -167,27 +170,66 @@ int z_alloc_fd(void *obj, const struct fd_op_vtable *vtable)

#ifdef CONFIG_POSIX_API

ssize_t read(int fd, void *buf, size_t sz)
ssize_t z_impl_sys_read(int fd, void *buf, size_t sz)
{
if (_check_fd(fd) < 0) {
return -1;
}

return fdtable[fd].vtable->read(fdtable[fd].obj, buf, sz);
}

#ifdef CONFIG_USERSPACE
ssize_t z_vrfy_sys_read(int fd, void *buf, size_t sz)
{
if (Z_SYSCALL_MEMORY_WRITE(buf, sz)) {
errno = EFAULT;
return -1;
}

return z_impl_sys_read(fd, buf, sz);
}
#include <syscalls/sys_read_mrsh.c>
#endif /* CONFIG_USERSPACE */

/* Normal C function wrapping a corresponding syscall. Required to ensure
* classic C linkage.
*/
ssize_t read(int fd, void *buf, size_t sz)
{
return sys_read(fd, buf, sz);
}
FUNC_ALIAS(read, _read, ssize_t);

ssize_t write(int fd, const void *buf, size_t sz)
ssize_t z_impl_sys_write(int fd, const void *buf, size_t sz)
{
if (_check_fd(fd) < 0) {
return -1;
}

return fdtable[fd].vtable->write(fdtable[fd].obj, buf, sz);
}

#ifdef CONFIG_USERSPACE
ssize_t z_vrfy_sys_write(int fd, const void *buf, size_t sz)
{
Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, sz));

return z_impl_sys_write(fd, buf, sz);
}
#include <syscalls/sys_write_mrsh.c>
#endif /* CONFIG_USERSPACE */

/* Normal C function wrapping a corresponding syscall. Required to ensure
* classic C linkage.
*/
ssize_t write(int fd, const void *buf, size_t sz)
{
return sys_write(fd, buf, sz);
}
FUNC_ALIAS(write, _write, ssize_t);

int close(int fd)
int z_impl_sys_close(int fd)
{
int res;

Expand All @@ -200,6 +242,19 @@ int close(int fd)

return res;
}

#ifdef CONFIG_USERSPACE
ssize_t z_vrfy_sys_close(int fd)
{
return z_impl_sys_close(fd);
}
#include <syscalls/sys_close_mrsh.c>
#endif /* CONFIG_USERSPACE */

int close(int fd)
{
return sys_close(fd);
}
FUNC_ALIAS(close, _close, int);

int fsync(int fd)
Expand Down

0 comments on commit c2bc3fd

Please sign in to comment.