-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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 + kernel: support for realtime signals #74918
base: main
Are you sure you want to change the base?
Conversation
431b3cd
to
9f9125e
Compare
Works on my desk ¯\(ツ)/¯ twister --retry-failed 3 -T tests/posix/common -T tests/kernel/signal/
INFO - Using Ninja..
INFO - Zephyr version: v3.7.0-rc1-12-gc284b50da617
INFO - Using 'zephyr' toolchain.
INFO - Selecting default platforms per test case
INFO - Building initial testsuite list...
INFO - Writing JSON report /home/cfriedt/zephyrproject/zephyr/twister-out/testplan.json
INFO - JOBS: 32
INFO - Adding tasks to the queue...
INFO - Added initial list of jobs to queue
INFO - Total complete: 562/ 562 100% skipped: 272, failed: 0, error: 0
INFO - 16 test scenarios (562 test instances) selected, 272 configurations skipped (246 by static filter, 26 at runtime).
INFO - 290 of 562 test configurations passed (100.00%), 0 failed, 0 errored, 272 skipped with 0 warnings in 696.02 seconds
INFO - In total 23167 test cases were executed, 27603 skipped on 41 out of total 757 platforms (5.42%)
INFO - 288 test configurations executed on platforms, 2 test configurations were only built.
INFO - Saving reports...
INFO - Writing JSON report /home/cfriedt/zephyrproject/zephyr/twister-out/twister.json
INFO - Writing xunit report /home/cfriedt/zephyrproject/zephyr/twister-out/twister.xml...
INFO - Writing xunit report /home/cfriedt/zephyrproject/zephyr/twister-out/twister_report.xml...
INFO - Run completed |
f44d683
to
a503415
Compare
2badd25
to
dcaf32d
Compare
|
dcaf32d
to
624b350
Compare
|
I'm still seeing weirdness in the Doxygen output. Not entirely sure how to fix this. @kartben - have you ever seen this before? |
Is there a reason you're using |
@cfriedt if you want to use |
Move initializers to a common macro and provide static variants. Signed-off-by: Chris Friedt <[email protected]>
This changes adds initial support for signals. Note: this feature is experimental. The primary use-case is intended to be real-time signals. Currently, there is no asynchronous signal delivery. Signed-off-by: Chris Friedt <[email protected]>
Add tests for realtime signals. Signed-off-by: Chris Friedt <[email protected]>
Add a document describing the signal API. Provide details on * manipulating signal sets * manipulating the signal mask of the current thread * sending (queuing) a signal * receiving (waiting-on) a signal Signed-off-by: Chris Friedt <[email protected]>
Add support for the _POSIX_REALTIME_SIGNALS Option. This adds support for the functions sigqueue(), sigtimedwait(), and sigwaitinfo(). Signed-off-by: Chris Friedt <[email protected]>
Add tests for realtime signals. Note, that since the "is a" relationship between Zephyr and POSIX threads is not bidirectional, tests need to run inside of a POSIX thread in order to correctly translate a "pid_t" (which is necessarily an int due to it being defined as such in various C libraries) to a pthread_t, and subsequently to a k_tid_t. Of course, the kernel counterparts of the real-time signal API have no such restriction, as k_pid_t aliases k_tid_t. Signed-off-by: Chris Friedt <[email protected]>
Mark the POSIX_REALTIME_SIGNALS Option Group (and Option) as supported in Zephyr. This and POSIX_THREAD_SAFE_FUNCTIONS (as well as the other PRs for POSIX_DEVICE_IO, POSIX_FD_MGMT, and POSIX_SIGNALS) should make us functionally complete for the required system interfaces as well as PSE51. Signed-off-by: Chris Friedt <[email protected]>
Now that POSIX_REALTIME_SIGNALS is implemented, add the final piece of the POSIX_THREADS puzzle. Namely, pthread_kill(). This was the last function required to mark the POSIX_THREADS_BASE Option Group as fully supported in Zephyr. Additionally, we may now mark the _POSIX_THREADS Option as supported in Zephyr. The _POSIX_THREADS Option is required as part of the POSIX System Interfaces (Base Definitions) as well as PSE51, PSE52, PSE53, PSE54 and all other conformant POSIX subprofiles. Signed-off-by: Chris Friedt <[email protected]>
Test for pthread_kill() in signal.h Signed-off-by: Chris Friedt <[email protected]>
Mark the POSIX_THREADS_BASE Option Group as complete and mark the _POSIX_THREADS Option as supported. Signed-off-by: Chris Friedt <[email protected]>
624b350
to
4787f31
Compare
@jukkar, @ycsin - please revisit when you have a moment. |
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 have mixed feelings over the intro/use of k_pid_t
in the Zephyr APIs since the kernel actually do not support processes and not sure if it ever will, so instead of having this 'catch' in the Zephyr kernel layer, it might also make sense for us to simply treat thread as thread in Zephyr APIs and simply address/mention this limitation in the POSIX layer, but otherwise LGTM
@peter-mitsis , @andyross - would you be able to review this from the kernel side? |
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.
Years ago, Zephyr had a signal-like feature called alerts; however, this was removed in 2018 as no one was using it. This leads me to wonder, would it be better to have this entirely defined within the posix subsystem/library and not in the kernel?
#include <zephyr/sys/ring_buffer.h> | ||
|
||
#ifndef BITS_PER_BYTE | ||
#define BITS_PER_BYTE 8 |
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 am surprised that this is not already in something like include/zephyr/sys/util.h
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.
Yeah, same. I could factor that out into a separate commit or PR, if that works.
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.
Made #79479
return false; | ||
} | ||
|
||
if (_current == tid) { |
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 think that (_current == tid) can only be a valid check if done at thread level. If done at a ISR-level, a previous operation might have aborted it, but _current will have remained unchanged until execution leaves the interrupt.
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.
Thanks for the insight - what is the best way to get the thread associated with a given syscall behind the syscall? k_current_get()
?
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.
If I am following the intent of the logic correctly, all we really need for this fast path check is
if ((!arch_is_in_isr() && (_current == tid)) {
return true;
}
Thus, if the operation was called by a thread, it is safe to test _current against tid. If it was invoked by an ISR, we fall through to the next check just as if the routine was called by a thread other than itself.
if ((tid->base.thread_state & valid_states) != 0) { | ||
return true; | ||
} | ||
|
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 feel a little more comfortable if the valid states were testing for invalid states rather than assuming that if a valid state bit is set, then all is ok.
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 works - I'll make those changes.
static bool k_sig_pid_is_valid(k_pid_t pid) | ||
{ | ||
k_tid_t tid = (k_tid_t)pid; | ||
const uint32_t valid_states = _THREAD_PENDING | _THREAD_SUSPENDED | _THREAD_QUEUED; |
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.
What about _THREAD_SUSPENDING?
|
||
static void k_sig_pending_unlocked(struct k_sig_set *set) | ||
{ | ||
struct k_thread *tid = _current; |
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.
Is this supposed to be callable from within an ISR? Again, I am seeing a potential issue with confusing the thread with the interrupted thread if called from an ISR. (There may be other cases where this arises)
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.
This is really just a private function for use locally when the spinlock is already locked. It could probably be marked inline, but does not need to be inlined. I don't believe it would ever be called from an ISR context.
What is the best call to make to determine the thread ID associated with a syscall while the syscall is executing? k_current_get()
?
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.
When it comes to getting the current thread ID, _current can generally be used by kernel internals--I usually think of k_current_get() as being more application oriented.
I may have misread something, but it does look to me like this routine is ISR callable. It can be called by z_impl_k_sig_queue(), which in turn has documentation that explicitly states that it is safe to call in an ISR context. Given how it gets used, I suspect that all we would need is to make the k_sig_addset() also conditional upon the context not being an ISR.
if ((entry->tid == tid) && !arch_is_in_isr()) {
k_sig_addset(set, entry->signo);
}
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.
It might be possible to call this with tid as a parameter, which, I think would solidify the use.
It is static here, so use of this function should be from behind a syscall, and not an ISR.
} | ||
} | ||
|
||
static inline void k_sig_dump_set(const struct k_sig_set *set, const char *label) |
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.
Potential naming inconsistency: I observe that k_sig_fifo_dump() puts the verb 'dump' at the end whereas k_sig_dump_set() puts the verb in the second-to-last position.
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.
Yes - thanks. I'll fix that.
for reference: https://docs.zephyrproject.org/1.13.0/kernel/synchronization/alerts.html?highlight=alerts |
The primary reason is that, eventually, the same signal mechanism can be used by both libc and POSIX to signal threads (so that libc signals can be independent of POSIX). The second reason is that (currently) Zephyr threads are not POSIX threads, so if it were to be only available at the POSIX thread level, then there would be an asymmetric way to signal. This simplifies and future-proofs signalling so it is bidirectional. |
@cfriedt - Not sure if there is anything you need from me at the moment on this PR, but I thought I would ping you just in case I have overlooked something. |
@peter-mitsis - I have to respin. Just in Vienna at LPC this week. I'll make sure to check about ISR vs syscall context. |
I'd like to get #79479 in before this (to factor out the |
@cfriedt this needs rebasing |
This was required for practicality
These add support to the kernel
k_sigqueue()
andk_sigtimedwait()
These complete the
POSIX_REALTIME_SIGNALS
Option Group (and_POSIX_REALTIME_SIGNALS
Option)These add
pthread_kill()
to (finally) complete thePOSIX_THREADS_BASE
Option Group and_POSIX_THREADS
Optionpthread_kill()
pthread_kill()
Kernel Doc Preview
POSIX Doc Preview
Fixes #59943
Fixes #74993
Fixes #74994
Fixes #74995