-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
Define and document expected behavior of API calls in various contexts #18970
Comments
+1 to these.
No objections, but can you provide an example API function where you might want to use this term? I would expect all the driver APIs I can think of offhand to be interrupt-safe, at least when called from thread context.
I would suggest "might sleep" (or "may sleep") instead. This is more familiar from Linux kernel source code (648 matches for "might sleep" in v5.3), and has additional advantages beyond that. In particular, as discussed for By contrast, "might sleep" makes it clearer that the caller's thread might get scheduled out, and thus further hints the caller must be running in thread context.
So this would become e.g.:
Where the Sphinx
+1 to |
Never mind, I take it back. https://lwn.net/Articles/274695/
|
We need to be able to say succinctly "Unless otherwise specified all API functions are interrupt-safe" and expect people to know what that means. A specific example would be the GPIO API, where it is not clear to implementers that, because GPIO write functions may be invoked from ISRs, read-modify-write code like:
must be wrapped in a spin-lock to be interrupt-safe. Most implementations don't do that, even in the ongoing GPIO rewrite, in part because we couldn't get agreement in #19252 on what "interrupt-safe" meant and whether it was important to document that expectation before people started implementing drivers.
My intent was to identify functions that will not transfer control from a cooperative thread. "blocking" is a poorly chosen term. Scrap it and start over. Zephyr uses several terms including "Waiting", "Suspended", and "Ready" to identify started non-terminated non-running threads. The transitions we're interested in are "suspend" and "wait". Let's use "yield" for "suspends or waits". There are three cases:
So we can do:
It's non-yielding that we care about, because those functions guarantee, when invoked by a cooperative thread, that no other cooperative thread will be allowed to run before the function returns. (Absent bugs like #20255.) I'm not sure exactly how functions should be annotated with respect to their behavior, but I would want it to be terse and consistent.
Yes, but that relies on having API to provide information about context to callees, which we probably don't have. To be considered later. |
Excellent example, thank you. Summarizing the status:
Did you mean "The function invoked by a given thread" instead of "The thread invoking a given function"?
With the given definition of "yield" ("suspends or waits"), I agree these are the desired semantics. I also agree that defining terms in accordance with documented thread states and related APIs is a great approach. However, I'm still bullish on "might sleep" terminology-wise. I worry "yielding" is too easy to confuse with "may call k_yield()". |
This is an evolving document used to come to consensus on the set of defined terms necessary to precisely document the expected behavior of API calls in various contexts. It's in Markdown rather than reStructured Text because that's most convenient for the editor. This commit archives the original proposal in issue zephyrproject-rtos#18970. Signed-off-by: Peter Bigot <[email protected]>
See mbolivar comment at zephyrproject-rtos#18970 (comment) and subsequent discussion. Add Background section to reference and summarize key concepts from existing documentation, particularly for thread state and priority and execution context. Replaced "blocking" with "yielding" for precision and consistency with Zephyr thread terminology. Add Commentary subsections that give a bit of explanation for why something is important or how concepts relate to each other. Signed-off-by: Peter Bigot <[email protected]>
I've integrated the discussion so far into this document which is available for review through #20959 so people can comment on specific concerns in context. I think that'll be a bit more convenient then chained comments on this issue.
No. The operation of yielding is something that directly affects threads. The impact on functions is derived.
A problem is that traditionally Zephyr has used "sleep" to specifically mean "wait for a timeout to occur". I would rather that "suspend" was more general, but currently it specifically references waiting without an event. |
API meeting 19th May: Plan of action to document the expected behavior of public API functions in Zephyr:
During the 2.4 development cycle, begin each API meeting with a status update on the function properties. |
Here's my assessment of
Some notes on the table
Determining the behavior of the API is not trivial. Some of the above may be wrong. Some were surprises, like the functions to read the number of spaces available for read and write in I've identified 181 functions in This is gonna be really unpleasant. |
@andyross and @andrewboie could you please review the contents of this table? The terminology is further explained here: |
@pabigot was reading through all of this and was wondering why we use "sleep" (https://docs.zephyrproject.org/latest/reference/terminology.html#sleep). Sleeping is not a documented thread state. Is this the same as |
AFAIK yes |
The terminology was introduced in #21678 based on analysis in #20969. The term "sleep" ultimately came from here. To precisely describe what "put the caller to sleep" means to a user it became "a voluntary transition to a non-running active thread state". The documented thread states relevant to "sleep" are transition to either "waiting" and "suspended". Technically it would also cover "ready" but AFAIK there is no API that allows voluntary direct transition from running to ready. So the terminology does not reflect any internal kernel state names that implement the thread state machine. It's perhaps not too late to change, but I suspect "sleeps" will be more clear to people than "pends". |
Shorter: "sleeps" was intended to also describe a function that invokes |
update per zephyrproject-rtos#18970 (comment) Signed-off-by: Peter Bigot <[email protected]>
This issue is intended to cover the concerns raised in #1960, #3694, #6184, #17014, and related lack of clarity and consistency.
Proposal: We should have:
Also are
k_is_in_isr()
andk_is_preempt_thread()
sufficient to determine whether it's safe to proceed, or do we also needk_is_atomic()
, #17301, or other technologies?Example policies might be:
-EWOULDBLOCK
shall be returned in situations where the requested operation cannot be successfully completed in that context.If we can define the normal behavior at either a system or driver-specific level, only the exceptions need be documented at the individual function level.
The text was updated successfully, but these errors were encountered: