Skip to content

Commit

Permalink
libc: minimal: implement putc_unlocked & putchar_unlocked
Browse files Browse the repository at this point in the history
Add a simple implementation for putc_unlocked() &
putchar_unlocked().

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
  • Loading branch information
ycsin committed Jun 24, 2024
1 parent 87729ba commit 778629e
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 2 deletions.
4 changes: 2 additions & 2 deletions doc/services/portability/posix/option_groups/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,8 @@ This table lists service support status in Zephyr for `POSIX_FD_MGMT`:
funlockfile(), yes
getc_unlocked(),
getchar_unlocked(),
putc_unlocked(),
putchar_unlocked(),
putc_unlocked(), yes
putchar_unlocked(), yes

.. _posix_option_group_memory_protection:

Expand Down
2 changes: 2 additions & 0 deletions lib/libc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ config MINIMAL_LIBC
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;
}

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);
}
5 changes: 5 additions & 0 deletions lib/libc/minimal/include/stdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ 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_POSIX_FILE_LOCKING) || defined(__DOXYGEN__)
void flockfile(FILE *file);
int ftrylockfile(FILE *file);
Expand Down
1 change: 1 addition & 0 deletions lib/posix/options/file_locking.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stdio.h>

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

void zvfs_flockfile(int fd);
Expand Down
43 changes: 43 additions & 0 deletions tests/posix/common/src/file_locking.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,49 @@ ZTEST(file_locking, test_file_locking)
z_free_fd(POINTER_TO_INT(file));
}

void put_thread(void *p1, void *p2, void *p3)
{
FILE *file = p1;

/* Lock held in main thread */
zassert_not_ok(ftrylockfile(file));

/* Wait for the lock */
flockfile(file);
zassert_equal(putc_unlocked('S', file), 'S');
zassert_equal(putchar('T'), 'T');
funlockfile(file);
}

ZTEST(file_locking, test_stdio)
{
FILE *file = INT_TO_POINTER(z_alloc_fd(NULL, NULL));
struct k_thread test_thread;
int priority = k_thread_priority_get(k_current_get());

/* Lock the file before creating the test thread */
flockfile(file);

k_thread_create(&test_thread, test_stack, K_THREAD_STACK_SIZEOF(test_stack),
put_thread, file, INT_TO_POINTER(true), NULL, priority, 0,
K_NO_WAIT);

/* Allow the test thread to run */
k_msleep(100);
/* The test thread should be waiting for the lock */
zassert_equal(k_thread_join(&test_thread, K_MSEC(10)), -EAGAIN);

/* Main thread has the lock, either version should work */
zassert_equal(putc('T', file), 'T');
zassert_equal(putchar_unlocked('E'), 'E');

/* We are done with the file here, unlock it so that test thread can run */
funlockfile(file);
zassert_equal(k_thread_join(&test_thread, K_MSEC(100)), 0);

z_free_fd(POINTER_TO_INT(file));
}

#else
/**
* PicoLIBC doesn't support these functions in its header
Expand Down

0 comments on commit 778629e

Please sign in to comment.