Skip to content
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

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

cfriedt
Copy link
Member

@cfriedt cfriedt commented Jun 25, 2024

This was required for practicality

  • ring_buffer: support static rings

These add support to the kernel

  • kernel: initial support for signals
  • tests: kernel: add tests for k_sigqueue() and k_sigtimedwait()
  • doc: kernel: services: add a doc about signals

These complete the POSIX_REALTIME_SIGNALS Option Group (and _POSIX_REALTIME_SIGNALS Option)

  • posix: add realtime signal support
  • tests: posix: common: add tests for realtime signals
  • doc: posix: mark realtime signals as supported 🎉

These add pthread_kill() to (finally) complete the POSIX_THREADS_BASE Option Group and _POSIX_THREADS Option

  • posix: threads: implement pthread_kill()
  • tests: posix: headers: test for pthread_kill()
  • doc: posix: mark posix threads as supported 🎉

Kernel Doc Preview
POSIX Doc Preview

Fixes #59943
Fixes #74993
Fixes #74994
Fixes #74995

@cfriedt cfriedt requested review from ycsin, ceolin and jukkar June 25, 2024 02:47
@cfriedt cfriedt force-pushed the posix-realtime-signals2 branch 12 times, most recently from 431b3cd to 9f9125e Compare June 25, 2024 14:35
@cfriedt
Copy link
Member Author

cfriedt commented Jun 25, 2024

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

@cfriedt cfriedt force-pushed the posix-realtime-signals2 branch 4 times, most recently from f44d683 to a503415 Compare June 25, 2024 15:35
@cfriedt cfriedt marked this pull request as ready for review June 25, 2024 18:08
@zephyrbot zephyrbot added area: POSIX POSIX API Library area: Kernel area: Toolchains Toolchains area: Base OS Base OS Library (lib/os) labels Jun 25, 2024
@cfriedt
Copy link
Member Author

cfriedt commented Aug 10, 2024

  • removed reference to non-existent timeout parameter in k_sig_queue() doxygen

@cfriedt
Copy link
Member Author

cfriedt commented Aug 10, 2024

  • Fixed up references in signals.rst

@cfriedt
Copy link
Member Author

cfriedt commented Aug 10, 2024

I'm still seeing weirdness in the Doxygen output. Not entirely sure how to fix this. @kartben - have you ever seen this before?
Screenshot 2024-08-10 at 8 39 18 AM

@kartben
Copy link
Collaborator

kartben commented Aug 10, 2024

I'm still seeing weirdness in the Doxygen output. Not entirely sure how to fix this. @kartben - have you ever seen this before?
Screenshot 2024-08-10 at 8 39 18 AM

Is there a reason you're using @headerfile? Looks like the likely culprit (not sure why tho)

@cfriedt
Copy link
Member Author

cfriedt commented Aug 10, 2024

Is there a reason you're using @headerfile? Looks like the likely culprit (not sure why tho)

Actually, I added @headerfile thinking that would solve the problem, but it didn't help. With or without it was the same.

Then I reversed where @addtogroup and @defgroup were for the k_sig_apis group, and it half-worked. It now shows #include <signal.h> which is slightly correct. I think it would be preferable to use #include <zephyr/kernel.h> since kernel headers shouldn't be included directly.

Ahh... I see it's the same situation already for spinlocks.

Screenshot 2024-08-10 at 9 06 16 AM

At least it's not only a problem here, so I think my next push should be OK.

Have a nice weekend. Please take a look when the signals are green again, but no rush.

@kartben
Copy link
Collaborator

kartben commented Aug 10, 2024

@cfriedt if you want to use @headerfile tags (which I don't think you need, but I might be missing something), then double check the correct syntax for sharp brackets: https://www.doxygen.nl/manual/commands.html#cmdheaderfile

Chris Friedt added 10 commits August 10, 2024 09:08
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]>
@cfriedt
Copy link
Member Author

cfriedt commented Aug 11, 2024

@jukkar, @ycsin - please revisit when you have a moment.
@kartben - @headerfile isn't used anywhere else in Zephyr currently, so I would prefer to not introduce it. The #include ... bit seems to be generated by SHOW_HEADERFILE

Copy link
Member

@ycsin ycsin left a 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

@cfriedt
Copy link
Member Author

cfriedt commented Aug 20, 2024

@peter-mitsis , @andyross - would you be able to review this from the kernel side?

Copy link
Collaborator

@peter-mitsis peter-mitsis left a 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
Copy link
Collaborator

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

Copy link
Member Author

@cfriedt cfriedt Sep 2, 2024

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.

Copy link
Member Author

@cfriedt cfriedt Oct 6, 2024

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) {
Copy link
Collaborator

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.

Copy link
Member Author

@cfriedt cfriedt Sep 2, 2024

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()?

Copy link
Collaborator

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;
}

Copy link
Collaborator

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.

Copy link
Member Author

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;
Copy link
Collaborator

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;
Copy link
Collaborator

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)

Copy link
Member Author

@cfriedt cfriedt Sep 2, 2024

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()?

Copy link
Collaborator

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);
}

Copy link
Member Author

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)
Copy link
Collaborator

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.

Copy link
Member Author

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.

@nashif
Copy link
Member

nashif commented Aug 21, 2024

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?

for reference: https://docs.zephyrproject.org/1.13.0/kernel/synchronization/alerts.html?highlight=alerts

@cfriedt
Copy link
Member Author

cfriedt commented Aug 21, 2024

would it be better to have this entirely defined within the posix subsystem/library and not in the kernel?

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.

@peter-mitsis
Copy link
Collaborator

@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.

@cfriedt
Copy link
Member Author

cfriedt commented Sep 18, 2024

@peter-mitsis - I have to respin. Just in Vienna at LPC this week. I'll make sure to check about ISR vs syscall context.

@cfriedt
Copy link
Member Author

cfriedt commented Oct 13, 2024

I'd like to get #79479 in before this (to factor out the BITS_PER_BYTE macro). I have respun with changes requested, but will push after 79479 is in.

@kartben
Copy link
Collaborator

kartben commented Nov 27, 2024

@cfriedt this needs rebasing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet