-
Notifications
You must be signed in to change notification settings - Fork 7.4k
posix: Implement mq_notify() #67988
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
posix: Implement mq_notify() #67988
Conversation
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.
try not to modify unrelated lines, with the right config I think you can format just the modified lines in vscode
a2ef878
to
427b84b
Compare
@ycsin just tried to fix some formatting issues but don't need to do that |
427b84b
to
c15e5fe
Compare
Looks like you need a rebase |
514134a
to
579e0cd
Compare
579e0cd
to
3c861d4
Compare
tests/posix/common/src/mqueue.c
Outdated
struct mq_attr attrs; | ||
struct sigevent not; | ||
int32_t mode = 0777; | ||
int flags = O_RDWR | O_CREAT; | ||
|
||
attrs.mq_msgsize = MESSAGE_SIZE; | ||
attrs.mq_maxmsg = MESG_COUNT_PERMQ; | ||
|
||
not.sigev_notify_function = notify_function_basic; | ||
not.sigev_notify_attributes = NULL; | ||
not.sigev_notify = SIGEV_SIGNAL; | ||
not.sigev_value.sival_ptr = (void *)¬ification_executed; |
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.
Not a blocker, but attrs
and not
could be initialized where they are declared (we support C11 by default, so no need to use only C89 declarations). It might be a bit less verbose, but also, there would be no need to initialize anything to 0 / NULL
explicitly.
struct mq_attr attrs; | |
struct sigevent not; | |
int32_t mode = 0777; | |
int flags = O_RDWR | O_CREAT; | |
attrs.mq_msgsize = MESSAGE_SIZE; | |
attrs.mq_maxmsg = MESG_COUNT_PERMQ; | |
not.sigev_notify_function = notify_function_basic; | |
not.sigev_notify_attributes = NULL; | |
not.sigev_notify = SIGEV_SIGNAL; | |
not.sigev_value.sival_ptr = (void *)¬ification_executed; | |
struct mq_attr attrs = { | |
.mq_msgsize = MESSAGE_SIZE, | |
.mq_maxmsg = MESG_COUNT_PERMQ, | |
}; | |
struct sigevent not = { | |
.sigev_notify_function = notify_function_basic, | |
.sigev_notify = SIGEV_SIGNAL, | |
.sigev_value.sival_ptr = (void *)¬ification_executed, | |
}; | |
int32_t mode = 0777; | |
int flags = O_RDWR | O_CREAT; |
tests/posix/common/src/mqueue.c
Outdated
mqd_t mqd; | ||
struct mq_attr attrs; | ||
struct sigevent not; | ||
int32_t mode = 0777; | ||
int flags = O_RDWR | O_CREAT; | ||
|
||
attrs.mq_msgsize = MESSAGE_SIZE; | ||
attrs.mq_maxmsg = MESG_COUNT_PERMQ; | ||
|
||
not.sigev_notify = SIGEV_THREAD; | ||
not.sigev_value.sival_int = (int)pthread_self(); | ||
not.sigev_notify_function = notify_function_thread; | ||
not.sigev_notify_attributes = NULL; |
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.
Similar - again, not blocking, so if this does need a respin for any reason, it might be worth it.
mqd_t mqd; | |
struct mq_attr attrs; | |
struct sigevent not; | |
int32_t mode = 0777; | |
int flags = O_RDWR | O_CREAT; | |
attrs.mq_msgsize = MESSAGE_SIZE; | |
attrs.mq_maxmsg = MESG_COUNT_PERMQ; | |
not.sigev_notify = SIGEV_THREAD; | |
not.sigev_value.sival_int = (int)pthread_self(); | |
not.sigev_notify_function = notify_function_thread; | |
not.sigev_notify_attributes = NULL; | |
mqd_t mqd; | |
struct mq_attr attrs = { | |
.mq_msgsize = MESSAGE_SIZE, | |
.mq_maxmsg = MESG_COUNT_PERMQ, | |
}; | |
struct sigevent not = { | |
.sigev_notify = SIGEV_THREAD, | |
.sigev_value.sival_int = (int)pthread_self(), | |
.sigev_notify_function = notify_function_thread, | |
}; | |
int32_t mode = 0777; | |
int flags = O_RDWR | O_CREAT; |
tests/posix/common/src/mqueue.c
Outdated
mqd_t mqd; | ||
struct mq_attr attrs; | ||
struct sigevent not; | ||
int32_t mode = 0777; | ||
int flags = O_RDWR | O_CREAT; | ||
|
||
attrs.mq_msgsize = MESSAGE_SIZE; | ||
attrs.mq_maxmsg = MESG_COUNT_PERMQ; | ||
|
||
not.sigev_notify = SIGEV_NONE; | ||
not.sigev_value.sival_ptr = (void *)¬ification_executed; | ||
not.sigev_notify_function = notify_function_basic; | ||
not.sigev_notify_attributes = NULL; |
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.
Same - just a suggestion, not blocking, so you can ignore if there is no respin required.
mqd_t mqd; | |
struct mq_attr attrs; | |
struct sigevent not; | |
int32_t mode = 0777; | |
int flags = O_RDWR | O_CREAT; | |
attrs.mq_msgsize = MESSAGE_SIZE; | |
attrs.mq_maxmsg = MESG_COUNT_PERMQ; | |
not.sigev_notify = SIGEV_NONE; | |
not.sigev_value.sival_ptr = (void *)¬ification_executed; | |
not.sigev_notify_function = notify_function_basic; | |
not.sigev_notify_attributes = NULL; | |
mqd_t mqd; | |
struct mq_attr attrs = { | |
.mq_msgsize = MESSAGE_SIZE, | |
.mq_maxmsg = MESG_COUNT_PERMQ, | |
}; | |
struct sigevent not = { | |
.sigev_notify = SIGEV_NONE, | |
.sigev_value.sival_ptr = (void *)¬ification_executed, | |
.sigev_notify_function = notify_function_basic, | |
}; | |
int32_t mode = 0777; | |
int flags = O_RDWR | O_CREAT; |
tests/posix/common/src/mqueue.c
Outdated
@@ -97,4 +96,205 @@ ZTEST(mqueue, test_mqueue) | |||
zassert_false(mq_unlink(queue), "Not able to unlink Queue"); | |||
} | |||
|
|||
bool notification_executed; |
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.
Not blocking either, so only if a respin is needed.
bool notification_executed; | |
static bool notification_executed; |
lib/posix/mqueue.c
Outdated
mqueue_object *mqueue = (mqueue_object *)arg; | ||
struct sigevent *sevp = &mqueue->not; | ||
|
||
pthread_detach(pthread_self()); |
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.
Aside from calling pthread_detach()
, I think it might be necessary to use pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)
. Otherwise, calling pthread_cancel()
might have no (immediate) effect. It's a bit confusing, but asynchronous (in pthreads) means with respect to cancellation points.
#67871 for reference, since there was a similar recent issue in timer.c
It's kind of tricky as well, because calling pthread_detach()
on an already detached thread is undefined behaviour which might eventually result in an assertion.
To avoid that, it would be a good idea to call pthread_attr_setdetachstate()
in mq_notify()
when sigev_notify_attributes
is not NULL
. Otherwise, in mq_notify_thread()
, call pthread_detach()
only if sevp->sigev_notify_attributes
is NULL
.
3c861d4
to
561cbee
Compare
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.
No need to check the attr detachstate before setting it - otherwise basically done 👍
lib/posix/mqueue.c
Outdated
ret = pthread_attr_getdetachstate(notification->sigev_notify_attributes, | ||
&detachstate); | ||
if (ret != 0) { | ||
errno = ret; | ||
return -1; | ||
} | ||
if (detachstate != PTHREAD_CREATE_DETACHED) { |
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.
No need to check what the attr detachstate is before setting it
ret = pthread_attr_getdetachstate(notification->sigev_notify_attributes, | |
&detachstate); | |
if (ret != 0) { | |
errno = ret; | |
return -1; | |
} | |
if (detachstate != PTHREAD_CREATE_DETACHED) { | |
ret = pthread_attr_getdetachstate(notification->sigev_notify_attributes, | |
&detachstate); | |
if (ret != 0) { | |
errno = ret; | |
return -1; | |
} | |
if (detachstate != PTHREAD_CREATE_DETACHED) { |
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.
That's the way posix/timer.c
do it so maybe it should be changed there as well?
lib/posix/mqueue.c
Outdated
errno = ret; | ||
return -1; | ||
} | ||
} |
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.
} |
The function was the last missing piece of the `_POSIX_MESSAGE_PASSING` option group. Due to lack of signal subsystem in the Zephyr RTOS the `sigev_notify` member of the `sigevent` structure that describes the notification cannot be set to `SIGEV_SIGNAL` - this notification type is not implemented, the function will return -1 and set `errno` to `ENOSYS`. `mq_notify` documentation: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_notify.html Fixes zephyrproject-rtos#66958 Signed-off-by: Adam Wojasinski <[email protected]>
561cbee
to
2fa4e3e
Compare
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.
LGTM - thanks @awojasinski 👍
Adds test cases testing following features: - function error handling - basic notification type - thread notification type - adding notification to non-empty queue Signed-off-by: Adam Wojasinski <[email protected]>
Updates in documentation support for `mq_notify` API in `_POSIX_MESSAGE_PASSING` group option. Signed-off-by: Adam Wojasinski <[email protected]>
2fa4e3e
to
21bae31
Compare
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.
@awojasinski - if you're feeling generous, we could also use mq_timedreceive() and mq_timedsend() for the _POSIX_TIMEOUTS subprofiling option 😃 |
@cfriedt sure I'll take a look in my spare time |
The function was the last missing piece of the
_POSIX_MESSAGE_PASSING
option group. Due to lack of signal subsystem in the Zephyr RTOS
the
sigev_notify
member of thesigevent
structure that describesthe notification cannot be set to
SIGEV_SIGNAL
- this notificationtype is not implemented, the function will return -1 and set
errno
to
ENOSYS
.mq_notify
documentation:https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_notify.html
Fixes #66958