Skip to content

posix: implement other _POSIX_THREAD_SAFE_FUNCTIONS #74350

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions doc/services/portability/posix/option_groups/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -564,13 +564,13 @@ This table lists service support status in Zephyr for `POSIX_FD_MGMT`:
:header: API, Supported
:widths: 50,10

flockfile(),
ftrylockfile(),
funlockfile(),
getc_unlocked(),
getchar_unlocked(),
putc_unlocked(),
putchar_unlocked(),
flockfile(), yes
ftrylockfile(), yes
funlockfile(), yes
getc_unlocked(), yes :ref:`†<posix_undefined_behaviour>`
getchar_unlocked(), yes :ref:`†<posix_undefined_behaviour>`
putc_unlocked(), yes
putchar_unlocked(), yes

.. _posix_option_group_memory_protection:

Expand Down Expand Up @@ -901,11 +901,11 @@ _POSIX_THREAD_SAFE_FUNCTIONS

asctime_r(),
ctime_r(),
flockfile(),
ftrylockfile(),
funlockfile(),
getc_unlocked(),
getchar_unlocked(),
flockfile(), yes
ftrylockfile(), yes
funlockfile(), yes
getc_unlocked(), yes :ref:`†<posix_undefined_behaviour>`
getchar_unlocked(), yes :ref:`†<posix_undefined_behaviour>`
getgrgid_r(),
getgrnam_r(),
getpwnam_r(),
Expand Down
3 changes: 3 additions & 0 deletions lib/libc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ config MINIMAL_LIBC
imply COMMON_LIBC_MALLOC
imply COMMON_LIBC_CALLOC
imply COMMON_LIBC_REALLOCARRAY
select POSIX_FILE_LOCKING if POSIX_THREAD_SAFE_FUNCTIONS
select COMMON_LIBC_PUTC_UNLOCKED if POSIX_THREAD_SAFE_FUNCTIONS
select COMMON_LIBC_GETC_UNLOCKED if POSIX_THREAD_SAFE_FUNCTIONS
help
Build with minimal C library.

Expand Down
2 changes: 2 additions & 0 deletions lib/libc/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_THRD
source/thrd/tss.c
)

add_subdirectory(source)

# Prevent compiler from optimizing calloc into an infinite recursive call
zephyr_library_compile_options($<TARGET_PROPERTY:compiler,no_builtin_malloc>)
2 changes: 2 additions & 0 deletions lib/libc/common/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,5 @@ config COMMON_LIBC_THRD
default y
help
Common implementation of C11 <threads.h> API.

rsource "source/Kconfig"
4 changes: 4 additions & 0 deletions lib/libc/common/source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2024 Meta Platforms
# SPDX-License-Identifier: Apache-2.0

add_subdirectory_ifdef(CONFIG_COMMON_LIBC_STDIO stdio)
4 changes: 4 additions & 0 deletions lib/libc/common/source/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2024 Meta Platforms
# SPDX-License-Identifier: Apache-2.0

rsource "stdio/Kconfig"
5 changes: 5 additions & 0 deletions lib/libc/common/source/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) 2024 Meta Platforms
# SPDX-License-Identifier: Apache-2.0

zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_GETC_UNLOCKED getc_unlocked.c)
zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_PUTC_UNLOCKED putc_unlocked.c)
19 changes: 19 additions & 0 deletions lib/libc/common/source/stdio/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (c) 2024 Meta Platforms
# SPDX-License-Identifier: Apache-2.0

config COMMON_LIBC_STDIO
bool
help
common function implementation in stdio.h

config COMMON_LIBC_GETC_UNLOCKED
bool
select COMMON_LIBC_STDIO
help
common implementation of getc_unlocked() & getchar_unlocked().

config COMMON_LIBC_PUTC_UNLOCKED
bool
select COMMON_LIBC_STDIO
help
common implementation of putc_unlocked() & putchar_unlocked().
24 changes: 24 additions & 0 deletions lib/libc/common/source/stdio/getc_unlocked.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2024 Meta Platforms
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <errno.h>
#include <stdio.h>

#include <zephyr/sys/util.h>

int getc_unlocked(FILE *stream)
{
ARG_UNUSED(stream);

errno = ENOSYS;

return EOF;
}
Comment on lines +12 to +19
Copy link
Member

Choose a reason for hiding this comment

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

For this one, I would add a zvfs_getc_unlocked() and just call that.

zvfs_getc_unlocked() should do some basic error checking but should not incur lock overhead.

E.g. check to see if stream is a valid pointer with IS_ARRAY_ELEMENT(), check the read() vtable method is non-NULL, etc.


int getchar_unlocked(void)
{
return getc_unlocked(stdin);
}
19 changes: 19 additions & 0 deletions lib/libc/common/source/stdio/putc_unlocked.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2024 Meta Platforms
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdio.h>

#include <zephyr/sys/libc-hooks.h>

int putc_unlocked(int c, FILE *stream)
{
return zephyr_fputc(c, stream);
}

int putchar_unlocked(int c)
{
return putc_unlocked(c, stdout);
}
16 changes: 16 additions & 0 deletions lib/libc/minimal/include/stdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ size_t fwrite(const void *ZRESTRICT ptr, size_t size, size_t nitems,
#define putc(c, stream) fputc(c, stream)
#define putchar(c) putc(c, stdout)

#if defined(CONFIG_COMMON_LIBC_PUTC_UNLOCKED) || defined(__DOXYGEN__)
int putc_unlocked(int c, FILE *stream);
int putchar_unlocked(int c);
#endif /* CONFIG_COMMON_LIBC_PUTC_UNLOCKED || __DOXYGEN__ */

#if defined(CONFIG_COMMON_LIBC_GETC_UNLOCKED) || defined(__DOXYGEN__)
int getc_unlocked(FILE *stream);
int getchar_unlocked(void);
#endif /* CONFIG_COMMON_LIBC_GETC_UNLOCKED || __DOXYGEN__ */

#if defined(CONFIG_POSIX_FILE_LOCKING) || defined(__DOXYGEN__)
void flockfile(FILE *file);
int ftrylockfile(FILE *file);
void funlockfile(FILE *file);
#endif /* CONFIG_POSIX_FILE_LOCKING || __DOXYGEN__ */

#ifdef __cplusplus
}
#endif
Expand Down
29 changes: 29 additions & 0 deletions lib/os/fdtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,35 @@ int zvfs_fsync(int fd)
return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_FSYNC);
}

#if defined(CONFIG_POSIX_FILE_LOCKING)
void zvfs_flockfile(int fd)
{
if (_check_fd(fd) < 0) {
return;
}

(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
}

int zvfs_ftrylockfile(int fd)
{
if (_check_fd(fd) < 0) {
return -1;
}

return k_mutex_lock(&fdtable[fd].lock, K_NO_WAIT);
}

void zvfs_funlockfile(int fd)
{
if (_check_fd(fd) < 0) {
return;
}

(void)k_mutex_unlock(&fdtable[fd].lock);
}
#endif /* CONFIG_POSIX_FILE_LOCKING */

static inline off_t zvfs_lseek_wrap(int fd, int cmd, ...)
{
off_t res;
Expand Down
1 change: 1 addition & 0 deletions lib/posix/options/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK mlockall.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK_RANGE mlock.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_MEMORY_PROTECTION mprotect.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_MAPPED_FILES mmap.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_LOCKING file_locking.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS
sleep.c
Expand Down
1 change: 1 addition & 0 deletions lib/posix/options/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ rsource "Kconfig.barrier"
rsource "Kconfig.c_lib_ext"
rsource "Kconfig.device_io"
rsource "Kconfig.fd_mgmt"
rsource "Kconfig.file_locking"
rsource "Kconfig.fs"
rsource "Kconfig.mem"
rsource "Kconfig.mqueue"
Expand Down
38 changes: 38 additions & 0 deletions lib/posix/options/Kconfig.file_locking
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (c) 2024 Meta Platforms
#
# SPDX-License-Identifier: Apache-2.0

config POSIX_FILE_LOCKING
bool "POSIX file locking [EXPERIMENTAL]"
select EXPERIMENTAL
select FDTABLE
help
Select 'y' here and Zephyr will provide implementations for the POSIX_FILE_LOCKING Option
Group.
This includes support for flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(),
getchar_unlocked(), putc_unlocked() and putchar_unlocked().

For more information, please see
https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html

if POSIX_FILE_LOCKING

# These options are intended to be used for compatibility with external POSIX
# implementations such as those in Newlib or Picolibc.

config POSIX_FD_MGMT_ALIAS_FLOCKFILE
bool
help
Select 'y' here and Zephyr will provide an alias for flockfile() as _flockfile().

config POSIX_FD_MGMT_ALIAS_FTRYLOCKFILE
bool
help
Select 'y' here and Zephyr will provide an alias for ftrylockfile() as _ftrylockfile().

config POSIX_FD_MGMT_ALIAS_FUNLOCKFILE
bool
help
Select 'y' here and Zephyr will provide an alias for funlockfile() as _funlockfile().

endif # POSIX_FILE_LOCKING
1 change: 1 addition & 0 deletions lib/posix/options/Kconfig.pthread
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ config POSIX_THREAD_PRIO_PROTECT

config POSIX_THREAD_SAFE_FUNCTIONS
bool "POSIX thread-safe functions"
select POSIX_FILE_LOCKING
help
Select 'y' here to enable POSIX thread-safe functions including asctime_r(), ctime_r(),
flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(), getchar_unlocked(),
Expand Down
39 changes: 39 additions & 0 deletions lib/posix/options/file_locking.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024 Meta Platforms
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <errno.h>
#include <stdio.h>

#include <zephyr/sys/libc-hooks.h>
#include <zephyr/sys/util.h>

void zvfs_flockfile(int fd);
int zvfs_ftrylockfile(int fd);
void zvfs_funlockfile(int fd);

void flockfile(FILE *file)
{
zvfs_flockfile(POINTER_TO_INT(file));
}
#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_FLOCKFILE
FUNC_ALIAS(flockfile, _flockfile, void);
#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FLOCKFILE */

int ftrylockfile(FILE *file)
{
return zvfs_ftrylockfile(POINTER_TO_INT(file));
}
#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_FTRYLOCKFILE
FUNC_ALIAS(ftrylockfile, _ftrylockfile, int);
#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FTRYLOCKFILE */

void funlockfile(FILE *file)
{
zvfs_funlockfile(POINTER_TO_INT(file));
}
#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_FUNLOCKFILE
FUNC_ALIAS(funlockfile, _funlockfile, void);
#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FUNLOCKFILE */
Loading
Loading