Page MenuHomeFreeBSD

runq: API rationalization, code factorization, revised implementation
ClosedPublic

Authored by olce on May 27 2024, 10:27 PM.
Tags
None
Referenced Files
Unknown Object (File)
Wed, Aug 6, 6:26 AM
Unknown Object (File)
Tue, Aug 5, 9:07 PM
Unknown Object (File)
Mon, Aug 4, 11:01 PM
Unknown Object (File)
Mon, Aug 4, 10:22 AM
Unknown Object (File)
Sat, Aug 2, 4:58 AM
Unknown Object (File)
Wed, Jul 30, 3:19 PM
Unknown Object (File)
Tue, Jul 29, 3:33 AM
Unknown Object (File)
Mon, Jul 28, 9:13 PM

Details

Reviewers
jhb
markj
mav
jeff
andrew
manu
kib
Commits
rG16cfdebb8b34: runq: New runq_findq(), common low-level search implementation
rG9eba574a6761: runq: New function runq_is_queue_empty(); Use it in ULE
rGbd97078d704b: runq: Tidy up and rename runq_setbit() and runq_clrbit()
rGbfd59136bece: runq: runq_check(): Re-implement on top of runq_findq()
rGde0e1a3abf8b: runq: Revamp runq_find*(), new runq_find_range()
rG606087082472: runq: Re-order functions more logically
rG000ffb6f24c4: runq: More macros; Better and more consistent naming
rG55731b34c3ff: runq: API tidy up: 'pri' => 'idx', 'idx' as int, remove runq_remove_idx()
rGb6e0a4f51747: runq: Clarity and style pass
rG3020792db818: runq: Hide function prototypes under _KERNEL
rG3f5f50ca526f: runq: More selective includes of <sys/runq.h> to reduce pollution
rGfac3e1d3bc19: runq: Deduce most parameters, remove machine headers
rG9c3f4682bb90: runq: New runq_findq(), common low-level search implementation
rGa31193172cb9: runq: New function runq_is_queue_empty(); Use it in ULE
rG757bab06fb59: runq: Tidy up and rename runq_setbit() and runq_clrbit()
rGde78657a3aef: runq: runq_check(): Re-implement on top of runq_findq()
rG439dc920f2d8: runq: Revamp runq_find*(), new runq_find_range()
rG200fc93dace7: runq: Re-order functions more logically
rG7e2502e3dec9: runq: More macros; Better and more consistent naming
rGa11926f2a5f0: runq: API tidy up: 'pri' => 'idx', 'idx' as int, remove runq_remove_idx()
rG57540a0666f6: runq: Clarity and style pass
rG28b54827f5c1: runq: Hide function prototypes under _KERNEL
rG2fefe2c88b31: runq: Deduce most parameters, remove machine headers
rGc21c24adde98: runq: More selective includes of <sys/runq.h> to reduce pollution
Summary

Please see overview of project at D45393.

  1. Deduce most parameters, remove machine-specific headers.
  2. More selective includes of <sys/runq.h> to reduce pollution
  3. Hide function prototypes under _KERNEL
  4. API tidy up: 'pri' => 'idx', 'idx' as int, remove runq_remove_idx() (knows some ULE's internals).
  5. Code clarity and style
  6. Better and more consistent naming; More macros
  7. Re-order functions more logically
  8. Revamp runq_find*(), new runq_find_range()
  9. runq_check(): Re-implement on top of runq_findq()
  10. Tidy up and rename runq_setbit() and runq_clrbit()
  11. New function runq_is_queue_empty(); Use it in ULE
  12. New runq_findq(), common/unique low-level search implementation taking a range of queue indices and a predicate.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 57964
Build 54852: arc lint + arc unit

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
olce requested review of this revision.May 27 2024, 10:27 PM

Hopefully this is actually multiple commits. This change looks on its surface too large to review due to the 12 different things going on. .

In D45387#1035485, @imp wrote:

Hopefully this is actually multiple commits. This change looks on its surface too large to review due to the 12 different things going on. .

Yes, 12 commits exactly. Given they are in the same area and some of the same lines are changed by a few of them, I thought it would be best to start with grouping them to give an overview. I can of course publish all of them independently if/when needed. Perhaps some other grouping may ease the review. Let's see what others say.

jrtc27 added inline comments.
sys/sys/runq.h
57

Please check __SIZEOF_LONG__ == 4/8; you care about long here, not pointer size, but ILP32 / LP64 conflate the two (on 64-bit CHERI architectures like Morello and CHERI-RISC-V we have 8 byte long, unchanged, but 16 byte pointers)

sys/kern/kern_switch.c
334–335

Missing newlines here and in the other runq_sw_apply() wrappers below.

380
406
537

Why?

564–567

Why not check the bitset instead?

sys/sys/runq.h
99

Is there some reason we can't use bitset(9) for this?

sys/sys/sched.h
80

This change should be committed on its own, IMO.

olce marked 6 inline comments as done.

Incorporate suggestions.

sys/kern/kern_switch.c
334–335

This was kind of "passively deliberate". I usually put an empty new line at start if there are no declarations (old style), but at the same time style(9) now allows not putting them. I'm fine with both approaches.

The lines you're pointing at are indeed somewhat inconsistent with some other uses in this file, including some I introduced. I've just fixed that and settled for the old style. Given the extent of the changes, I could as well switch all relevant parts to the new style. What do you think?

537

Because it is then used by sched_ule.c in D45390. I could move it to <sys/runq.h> though.

564–567

That's what runq_first_thread() already does. It also fetches the first available thread which is not strictly necessary here, but then the caller (4BSD) needs to fetch it also, so I don't think this will make a practical difference with respect to the data cache and performance. Calling runq_first_thread() allows to save on instruction cache by not duplicating assembly code (which would be the case using bitset macros; but this could most probably be factorized in a separate function also). I'll see if/how I can rework that.

sys/sys/runq.h
57

I thought we were only supporting ILP32 or LP64 (see also arch(7)), that's the reason I chose to test for that. I've just changed it with your suggestion instead.

Even if CheriBSD is not FreeBSD, I would suggest that you (or some people working on it) update arch(7) in FreeBSD to reflect what CheriBSD as a downstream consumer does, so that people can generally be aware of such fundamental extensions that need support from upstream.

99

No special reason other than the original code didn't use it and, although aware of it, somehow I didn't connect the dots.

It seems some of the functionality that this work requires is missing in bitset(9), and I think it's a good opportunity to add it there. Otherwise, the functionality is really the same, so it would indeed be better to avoid code duplication.

I'll change that as a separate commit, for ease of commit/review, which will be grouped with the commits of this differential revision (so the change will appear here when it's done).

sys/sys/sched.h
80

Yes. This whole review in fact consists of 12 commits coalesced. This particular change is (currently) part of commit 4 ("API tidy up: 'pri' => 'idx', 'idx' as int, remove runq_remove_idx() (knows some ULE's internals)."). Does that answer your concern, or would like to see, e.g., the content of that specific commit?

sys/kern/kern_switch.c
334–335

It's the newline between } and static inline void not the first line of the fn Mark's talking about here

sys/kern/kern_switch.c
334–335

Checked with Mark, you're right.

This was also deliberate... I wanted to have a single herald comment for both the public function and the callback used to implement it (passed to runq_sw_apply()). Can I keep that like that? Else I'd move the herald comment close to the public function, unless you have some better suggestion?

olce marked 3 inline comments as done.

Rebase. Address comments. Remove RQSW_L2BPW.

sys/sys/runq.h
57

I finally decided to completely remove RQSW_L2BPW and let the compiler optimize / and % with RQSW_BPW as the dividend to simplify code a bit.

99

After an attempt to add the missing functionality in bitset(9) (last June), I concluded that doing so wasn't worth it, as it requires a lot of macrology, making it very hard to use, and potentially impacting changes for users (bitset(9)'s model is to have macros define all the required code, leading to unnecessary code and produced assembly duplication; departing from this scheme requires having macros that declare/define common functions which must then be used by consumers).

Additionally, implementing range scanning with predicates efficiently requires knowing the internals of bitset(9), and it seems they are supposed to stay opaque. So, I'm keeping the current implementation for now.

kib added inline comments.
sys/kern/kern_switch.c
374

Since runq already means 'run queue', the name is tautological.

sys/kern/sched_ule.c
2674–2676

Since you changing the return type, the function can be written much more concise now.
Also we have TD_IS_IDLETHREAD().

return (TDQ_LOAD(tdq) > (TD_IS_IDLETHREAD(curthread) ? 0 : 1);
sys/sys/runq.h
47

Move this somewhere like sys/_param.h or sys/_howmany.h, and include the _header from there and from sys/param.h.

63

This is GNU extension, and for all installed headers we do mark it with extension

64

ffsl() requires strings.h in userspace, and sys/libkern.h in kernel.

82

And this requires sys/queue.h.
To put it differently, I do not see why include some random headers, but not other, from the header.

122

constness for the value parameters is not too useful.

sys/sys/sched.h
67

Again, there is a lot of stuff that is needed to make the header compilable, and adding a random one there is not useful.

olce marked 8 inline comments as done.

Changes prompted by kib@ comments.

sys/kern/kern_switch.c
374

Although unfortunate, "run queue" designates the top structure holding all queues, and the predicate here only applies to a single queue within the run queue. The current naming respects that and is deliberate. Completely changing the terminology was out of scope for this change.

sys/kern/sched_ule.c
2674–2676

It could have been even with the previous type, as essentially the returned value has not changed.

That's much easier to read indeed.

sys/sys/runq.h
47

Done, see D50880.

64

Done here, but removing the include of strings.h later in this series, as I'm then preventing use of <sys/runq.h> from userspace. There's really nothing in this header that is user-serviceable, especially given that this series switches RQ_PPQ to 1 (and RQ_PPQ should just disappear, at least from userland, as it's an implementation detail irrelevant to the outside work after this work).

82

Simple: The includes you're talking about were already missing. I just added those related to my own additions.

I've just added them.

122

Not useful on x86, as these are passed in registers that are not callee-saved, but might be useful on other architectures. Anyway, I prefer that the signature reflects the expected implementation behavior.

sys/sys/sched.h
67

It's not a random one, but just the new one needed given modifications here (and that is useful, even if incomplete).

I've added others now. That said, I'll now refrain for doing such changes in this series. This wastes too much time because every following commit has to be rebased, and we can fix these issues afterwards.

kib added inline comments.
sys/kern/kern_switch.c
352–385

BTW, I am curious, is compiler smart enough to inline through the function pointer and directly emit andl instruction there, instead of generating a call to the op stub? Did you looked at the generated code?

This revision is now accepted and ready to land.Jun 16 2025, 5:13 PM
olce marked an inline comment as done.Jun 16 2025, 7:10 PM
olce added inline comments.
sys/kern/kern_switch.c
352–385

I looked at the generated code a while ago and the compiler was completely getting rid of the stub and inlining runq_sw_set_empty(). I've just check now and that hasn't changed (and same for runq_sw_set_not_empty()).