-
Notifications
You must be signed in to change notification settings - Fork 7.4k
posix: semaphore: implement named semaphore functions #67007
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
Conversation
sys_snode_t snode; | ||
sem_t sem; | ||
atomic_t ref_count; | ||
char *name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could avoid malloc if allocated like this
char name[CONFIG_SEM_NAMELEN_MAX];
I think we have this pattern in many places in the code space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm gonna gather more comments for this one, doing so will allocate a fixed sized array regardless of the actual length of the name.
Alternatively we can allocate the buffer for the nsem_obj
and the name
array in one go and the total memory allocated will depend on the name length. Ideally we would be able to k_realloc
the buffer once the sem is unlinked, however the k_realloc
isn't available (#41151), so I opted for the current implementation as the name buffer can be freed separately upon sem_unlink
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say a good follow-up PR would be to add static allocation support.
I'm ok with dynamic going in first and static coming in later, but I think both use cases are valuable for Zephyr.
The existing pattern that doesn't use malloc should be fine for filling the static gap later. Thanks for your help ❤️
@@ -2728,6 +2728,8 @@ POSIX API layer: | |||
status: maintained | |||
maintainers: | |||
- cfriedt | |||
collaborators: | |||
- ycsin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥳
f590fa8
to
2f76542
Compare
This code is racy.
When |
90b0fee
to
bec4c00
Compare
The code now looks correct, the race is gone. Here's some suggestions that aren't critical but could optimize the code
|
And another comment. You have:
Since this is used where a pointer is normally returned, it would be nicer
|
Hey @npitre, thanks for the suggestions! Regarding to point 2 and 3, I've added assert tests to make sure that the |
Updated to:
|
Add myself as a collaborator in the POSIX subsystem. Signed-off-by: Yong Cong Sin <[email protected]>
4767810
to
2d9c415
Compare
Consider these events:
I'll push this change with a few misc tidbits on top of your pull request. |
if (nsem->ref_count == 0) { | ||
__ASSERT(nsem->name == NULL, "ref_count is 0 but sem is not unlinked"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@npitre This means that the following behavior is guaranteed only when CONFIG_ASSERT
is enabled, is that intended?
If the semaphore has not been removed with a successful call to sem_unlink(), then sem_close() has no effect on the state of the semaphore.
i.e.: a named semaphore can be closed without being unlinked:
operation refcount change refcount state
----------------------------------------------------------------
sem_open() = 2 (created) 2
sem_close() - 1 1
sem_close() - 1 0
Yes. This would happen only if the semaphore user's code is buggy.
Yes, that is what the code does. The test suite exercizes that condition too.
That is a bad example. You normally must have balanced Multiple |
@@ -15,7 +15,7 @@ | |||
struct nsem_obj { | |||
sys_snode_t snode; | |||
sem_t sem; | |||
unsigned int ref_count; | |||
int ref_count; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@npitre I've modified other part that uses ref_count
to int
as well, and changed the overflow test from __ASSERT_NO_MSG(nsem->ref_count != UINT_MAX)
to __ASSERT_NO_MSG(nsem->ref_count != INT_MAX)
Implements `sem_open()`, `sem_unlink()` & `sem_close()` functions and added tests for them. Updated existing tests and POSIX docs. Signed-off-by: Yong Cong Sin <[email protected]>
The `sem_open()`, `sem_close()` & `sem_unlink()` functions are now implemented, so mark them as supported. Signed-off-by: Yong Cong Sin <[email protected]>
Localize a few public variables and refactor the test and functions so that they are reusable. Signed-off-by: Yong Cong Sin <[email protected]>
Run the normal semaphore test with a named semaphore. Signed-off-by: Yong Cong Sin <[email protected]>
- Regroup refcount decrement and semaphore destruction by making the linked state into a counted reference for it. This allows for simplifying the code and cleanly adding a few assertions in a common location. - Remove redundant initialization to NULL on memory about to be freed and local pointer in nsem_cleanup(). Signed-off-by: Nicolas Pitre <[email protected]>
- Adjust refcount checks with regards to previous commit. - Remove redundant zassert_not_null() on local pointers after a sem_close(). There is no implicit reference passing in C. Signed-off-by: Nicolas Pitre <[email protected]>
@npitre I've took the liberty to fold some of the fixes from your commits into the original commits where they where initially introduced and reworded your commits, but left the |
Implemented:
sem_open()
sem_close()
sem_unlink()
Fixes #66955
Fixes #66956
Fixes #66957