Skip to content

Commit 5b969ad

Browse files
committed
posix: options: implement the POSIX_FILE_LOCKING Option Group
Provide an implementation of the POSIX_FILE_LOCKING Option Group. Signed-off-by: Chris Friedt <cfriedt@tenstorrent.com>
1 parent 0e64322 commit 5b969ad

File tree

6 files changed

+186
-12
lines changed

6 files changed

+186
-12
lines changed

lib/libc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ config PICOLIBC
8686
select LIBC_ERRNO if THREAD_LOCAL_STORAGE
8787
select NEED_LIBC_MEM_PARTITION
8888
select TC_PROVIDES_POSIX_C_LANG_SUPPORT_R
89+
select TC_PROVIDES_POSIX_FILE_LOCKING
8990
imply COMMON_LIBC_MALLOC
9091
depends on PICOLIBC_SUPPORTED
9192
help

lib/os/fdtable.c

Lines changed: 95 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -339,43 +339,37 @@ static bool supports_pread_pwrite(uint32_t mode)
339339
}
340340
}
341341

342-
static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write, const size_t *from_offset)
342+
static ssize_t zvfs_rw_unlocked(int fd, void *buf, size_t sz, bool is_write,
343+
const size_t *from_offset)
343344
{
344345
bool prw;
345346
ssize_t res;
346347
const size_t *off;
347348

348-
if (_check_fd(fd) < 0) {
349-
return -1;
350-
}
351-
352-
(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
353-
354349
prw = supports_pread_pwrite(fdtable[fd].mode);
355350
if (from_offset != NULL && !prw) {
356351
/*
357352
* Seekable file types should support pread() / pwrite() and per-fd offset passing.
358353
* Otherwise, it's a bug.
359354
*/
360355
errno = ENOTSUP;
361-
res = -1;
362-
goto unlock;
356+
return -1;
363357
}
364358

365359
/* If there is no specified from_offset, then use the current offset of the fd */
366360
off = (from_offset == NULL) ? &fdtable[fd].offset : from_offset;
367361

368362
if (is_write) {
369363
if (fdtable[fd].vtable->write_offs == NULL) {
370-
res = -1;
371364
errno = EIO;
365+
return -1;
372366
} else {
373367
res = fdtable[fd].vtable->write_offs(fdtable[fd].obj, buf, sz, *off);
374368
}
375369
} else {
376370
if (fdtable[fd].vtable->read_offs == NULL) {
377-
res = -1;
378371
errno = EIO;
372+
return -1;
379373
} else {
380374
res = fdtable[fd].vtable->read_offs(fdtable[fd].obj, buf, sz, *off);
381375
}
@@ -388,7 +382,21 @@ static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write, const size_t
388382
fdtable[fd].offset += res;
389383
}
390384

391-
unlock:
385+
return res;
386+
}
387+
388+
static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write, const size_t *from_offset)
389+
{
390+
ssize_t res;
391+
392+
if (_check_fd(fd) < 0) {
393+
return -1;
394+
}
395+
396+
(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
397+
398+
res = zvfs_rw_unlocked(fd, buf, sz, is_write, from_offset);
399+
392400
k_mutex_unlock(&fdtable[fd].lock);
393401

394402
return res;
@@ -562,6 +570,81 @@ int zvfs_ioctl(int fd, unsigned long request, va_list args)
562570
return fdtable[fd].vtable->ioctl(fdtable[fd].obj, request, args);
563571
}
564572

573+
int zvfs_lock_file(FILE *file, k_timeout_t timeout)
574+
{
575+
int fd;
576+
int prev_errno;
577+
struct fd_entry *entry;
578+
579+
fd = z_libc_file_get_fd(file);
580+
prev_errno = errno;
581+
if (_check_fd(fd) < 0) {
582+
if (errno != prev_errno) {
583+
errno = prev_errno;
584+
}
585+
return -1;
586+
}
587+
588+
entry = &fdtable[fd];
589+
return k_mutex_lock(&entry->lock, timeout);
590+
}
591+
592+
int zvfs_unlock_file(FILE *file)
593+
{
594+
int fd;
595+
int prev_errno;
596+
struct fd_entry *entry;
597+
598+
fd = z_libc_file_get_fd(file);
599+
prev_errno = errno;
600+
if (_check_fd(fd) < 0) {
601+
if (errno != prev_errno) {
602+
errno = prev_errno;
603+
}
604+
return -1;
605+
}
606+
607+
entry = &fdtable[fd];
608+
return k_mutex_unlock(&entry->lock);
609+
}
610+
611+
int zvfs_getc_unlocked(FILE *stream)
612+
{
613+
int fd;
614+
int res;
615+
char buf;
616+
617+
fd = z_libc_file_get_fd(stream);
618+
if (_check_fd(fd) < 0) {
619+
return EOF;
620+
}
621+
622+
res = zvfs_rw_unlocked(fd, &buf, 1, false, NULL);
623+
if (res <= 0) {
624+
return EOF;
625+
}
626+
627+
return (int)buf;
628+
}
629+
630+
int zvfs_putc_unlocked(int c, FILE *stream)
631+
{
632+
int fd;
633+
int res;
634+
char buf = (char)c;
635+
636+
fd = z_libc_file_get_fd(stream);
637+
if (_check_fd(fd) < 0) {
638+
return EOF;
639+
}
640+
641+
res = zvfs_rw_unlocked(fd, &buf, 1, true, NULL);
642+
if (res <= 0) {
643+
return EOF;
644+
}
645+
646+
return c;
647+
}
565648

566649
#if defined(CONFIG_POSIX_DEVICE_IO)
567650
/*

lib/posix/options/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ if (NOT CONFIG_TC_PROVIDES_POSIX_FD_MGMT)
6767
)
6868
endif()
6969

70+
if (NOT CONFIG_TC_PROVIDES_POSIX_FILE_LOCKING)
71+
zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_LOCKING
72+
file_locking.c
73+
)
74+
endif()
75+
7076
if (NOT CONFIG_TC_PROVIDES_POSIX_FILE_SYSTEM)
7177
zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c)
7278
endif()

lib/posix/options/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rsource "Kconfig.c_lang_r"
1414
rsource "Kconfig.c_lib_ext"
1515
rsource "Kconfig.device_io"
1616
rsource "Kconfig.fd_mgmt"
17+
rsource "Kconfig.file_locking"
1718
rsource "Kconfig.file_system_r"
1819
rsource "Kconfig.fs"
1920
rsource "Kconfig.mem"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright (c) 2024 Tenstorrent AI ULC
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
config POSIX_FILE_LOCKING
6+
bool "POSIX file locking"
7+
help
8+
Select 'y' here and the following functions will be available:
9+
10+
flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(), getchar_unlocked(),
11+
putc_unlocked(), putchar_unlocked().
12+
13+
For more information, please see
14+
https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html

lib/posix/options/file_locking.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2024 Tenstorrent AI ULC
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <errno.h>
8+
#include <stdio.h>
9+
10+
#include <zephyr/toolchain.h>
11+
#include <zephyr/sys/fdtable.h>
12+
13+
int zvfs_lock_file(FILE *file, k_timeout_t timeout);
14+
int zvfs_unlock_file(FILE *file);
15+
int zvfs_getc_unlocked(FILE *stream);
16+
int zvfs_putc_unlocked(int c, FILE *stream);
17+
18+
/*
19+
* This is incorrectly declared by (at least) newlib to be a macro with 2 arguments
20+
* but it only takes 1 argument.
21+
*
22+
* Undefine any possible macro before attempting to define a duplicately-named function.
23+
*/
24+
#undef putchar_unlocked
25+
26+
/*
27+
* This is incorrectly declared by (at least) newlib to be a macro with 0 arguments
28+
* but it should take 1 argument.
29+
*
30+
* Undefine any possible macro before attempting to define a duplicately-named function.
31+
*/
32+
#undef getchar_unlocked
33+
34+
void flockfile(FILE *file)
35+
{
36+
while (zvfs_lock_file(file, K_FOREVER) != 0) {
37+
k_yield();
38+
}
39+
}
40+
41+
int ftrylockfile(FILE *file)
42+
{
43+
return zvfs_lock_file(file, K_NO_WAIT);
44+
}
45+
46+
void funlockfile(FILE *file)
47+
{
48+
(void)zvfs_unlock_file(file);
49+
}
50+
51+
int getc_unlocked(FILE *stream)
52+
{
53+
return zvfs_getc_unlocked(stream);
54+
}
55+
56+
int getchar_unlocked(void)
57+
{
58+
return zvfs_getc_unlocked(stdin);
59+
}
60+
61+
int putc_unlocked(int c, FILE *stream)
62+
{
63+
return zvfs_putc_unlocked(c, stream);
64+
}
65+
66+
int putchar_unlocked(int c)
67+
{
68+
return zvfs_putc_unlocked(c, stdout);
69+
}

0 commit comments

Comments
 (0)