-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
posix: implement file locking functions
Implement file locking functions and added testcase. Signed-off-by: Yong Cong Sin <ycsin@meta.com>
- Loading branch information
Showing
10 changed files
with
236 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright (c) 2024 Meta Platforms | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <stdio.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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
* Copyright (c) 2024, Meta Platforms | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <stdio.h> | ||
|
||
#include <zephyr/sys/fdtable.h> | ||
#include <zephyr/ztest.h> | ||
|
||
#ifndef CONFIG_PICOLIBC | ||
|
||
K_THREAD_STACK_DEFINE(test_stack, 1024); | ||
|
||
#define LOCK_SHOULD_PASS (void *)true | ||
#define LOCK_SHOULD_FAIL (void *)false | ||
#define UNLOCK_FILE (void *)true | ||
#define NO_UNLOCK_FILE (void *)false | ||
|
||
void ftrylockfile_thread(void *p1, void *p2, void *p3) | ||
{ | ||
int ret; | ||
FILE *file = p1; | ||
bool success = (bool)p2; | ||
bool unlock = (bool)p3; | ||
|
||
if (success) { | ||
ret = ftrylockfile(file); | ||
zassert_ok(ret, "Expected ftrylockfile to succeed but it failed: %d", ret); | ||
if (unlock) { | ||
funlockfile(file); | ||
} | ||
} else { | ||
zassert_not_ok(ftrylockfile(file), | ||
"Expected ftrylockfile to failed but it succeeded"); | ||
} | ||
} | ||
|
||
void flockfile_thread(void *p1, void *p2, void *p3) | ||
{ | ||
FILE *file = p1; | ||
bool success = (bool)p2; | ||
bool unlock = (bool)p3; | ||
|
||
flockfile(file); | ||
|
||
if (!success) { | ||
/* Shouldn't be here if it supposed to fail */ | ||
ztest_test_fail(); | ||
} | ||
|
||
if (unlock) { | ||
funlockfile(file); | ||
} | ||
} | ||
|
||
ZTEST(file_locking, test_file_locking) | ||
{ | ||
FILE *file = INT_TO_POINTER(z_alloc_fd(NULL, NULL)); | ||
int priority = k_thread_priority_get(k_current_get()); | ||
struct k_thread test_thread; | ||
|
||
/* Lock 5 times with flockfile */ | ||
for (int i = 0; i < 5; i++) { | ||
flockfile(file); | ||
} | ||
|
||
/* Lock 5 times with ftrylockfile */ | ||
for (int i = 0; i < 5; i++) { | ||
zassert_ok(ftrylockfile(file)); | ||
} | ||
|
||
/* Spawn a thread that uses ftrylockfile(), it should fail immediately */ | ||
k_thread_create(&test_thread, test_stack, K_THREAD_STACK_SIZEOF(test_stack), | ||
ftrylockfile_thread, file, LOCK_SHOULD_FAIL, NO_UNLOCK_FILE, priority, 0, | ||
K_NO_WAIT); | ||
/* The thread should terminate immediately */ | ||
zassert_ok(k_thread_join(&test_thread, K_MSEC(100))); | ||
|
||
/* Try agian with flockfile(), it should block forever */ | ||
k_thread_create(&test_thread, test_stack, K_THREAD_STACK_SIZEOF(test_stack), | ||
flockfile_thread, file, LOCK_SHOULD_FAIL, NO_UNLOCK_FILE, priority, 0, | ||
K_NO_WAIT); | ||
/* We expect the flockfile() call to block forever, so this will timeout */ | ||
zassert_equal(k_thread_join(&test_thread, K_MSEC(500)), -EAGAIN); | ||
/* Abort the test thread */ | ||
k_thread_abort(&test_thread); | ||
|
||
/* Unlock the file completely in this thread */ | ||
for (int i = 0; i < 10; i++) { | ||
funlockfile(file); | ||
} | ||
|
||
/* Spawn the thread again, which should be able to lock the file now with ftrylockfile() */ | ||
k_thread_create(&test_thread, test_stack, K_THREAD_STACK_SIZEOF(test_stack), | ||
ftrylockfile_thread, file, LOCK_SHOULD_PASS, UNLOCK_FILE, priority, 0, | ||
K_NO_WAIT); | ||
zassert_ok(k_thread_join(&test_thread, K_MSEC(100))); | ||
|
||
z_free_fd(POINTER_TO_INT(file)); | ||
} | ||
|
||
#else | ||
/** | ||
* PicoLIBC doesn't support these functions in its header | ||
* Skip the tests for now. | ||
*/ | ||
ZTEST(file_locking, test_file_locking) | ||
{ | ||
ztest_test_skip(); | ||
} | ||
#endif /* CONFIG_PICOLIBC */ | ||
|
||
ZTEST_SUITE(file_locking, NULL, NULL, NULL, NULL, NULL); |