Page MenuHomeFreeBSD

sched_ule: Fix selecting lowest priority thread early in corner case
AcceptedPublic

Authored by olce on Wed, Jun 24, 6:45 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Jul 14, 1:55 AM
Unknown Object (File)
Sat, Jul 11, 6:05 PM
Unknown Object (File)
Fri, Jul 10, 2:43 PM
Unknown Object (File)
Fri, Jul 10, 1:19 AM
Unknown Object (File)
Fri, Jul 10, 1:01 AM
Unknown Object (File)
Thu, Jul 9, 11:23 PM
Unknown Object (File)
Tue, Jul 7, 9:12 PM
Unknown Object (File)
Mon, Jul 6, 8:35 PM

Details

Summary

When transferring a thread with near 100% CPU statistics (but not 100%;
up to 57.5/59≈97.46%) to a CPU where the enqueue offset is ahead of at
least 2 from the dequeue one, which requires peculiar conditions to
happen (transfer triggered by a bind request or cpuset change, or during
balancing if a thread or more existed from a brief amount of time on the
origin CPU), the transferred thread can get placed after the dequeue
offset, effectively making it appear as a high priority one unduly,
causing latency increase for other threads.

The change here was missed when changing the enqueue and dequeue offsets
update mechanism to recover pre-256-queue-runqueue ULE anti-starvation
and fairness behavior. That change opened up the possibility that these
two offsets are apart by more than one.

Fixes: 6792f3411f6d ("sched_ule: Recover previous nice and anti-starvation behaviors")
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation

Diff Detail

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

Event Timeline

olce requested review of this revision.Wed, Jun 24, 6:45 PM
olce created this revision.
olce retitled this revision from ctld: Simplify handling of non-iSCSI and non-NVMe kernel ports to sched_ule: Fix selecting lowest priority thread early in corner case.
olce edited the summary of this revision. (Show Details)

Good commit this time.

Although it looks improbable, it might be the cause of the observed latency problem at Netflix.

We may have hit this one but that's not the one I'm testing a patch for right now. If it looks good in our setup I'll share it. It's a bit more of a fundamental scheduler change that we may or may not want to have enabled by default.

Do you have your tree for the stuff from your talk because, I'd like to compare notes. I had a few other odd behaviors I found. Some of them I didn't fix yet but couldn't tell if you did from your talk.

Also can someone with access on review make a sched group?

markj added inline comments.
sys/kern/sched_ule.c
507

Why does "pri" need to be an int?

556

This cast is unneeded, I believe, all of the operands here will undergo integer promotion before the result is computed.

560

You might add a little helper macro or function to normalize the index, since you're doing that three times here and the result isn't terribly easy to read.

This revision is now accepted and ready to land.Thu, Jul 2, 1:58 PM
olce marked 3 inline comments as done.

Simplify.

This revision now requires review to proceed.Thu, Jul 2, 4:22 PM
sys/kern/sched_ule.c
507

For a similar reason as for idx. pri is used in the initial computation of idx, which involves adding an offset and then a modulo. Adding the offset may cause a computation done on 8-bit to wraparound, causing a wrong mathematical result.

But arithmetic operators actually do the usual arithmetic conversions even when operands have same type, so this in fact unnecessary, going to undo this chunk.

556

Had a moment of doubt because I didn't think that the mere use of +/- would trigger arithmetic conversions (and hence, integer promotions), but that is explicitly written in the standard, and Godbolt confirms that in practice, so I'll just remove it.

This revision is now accepted and ready to land.Thu, Jul 2, 4:49 PM

For now I don't have enough time to visit this, so I'll take a look at this later. If I don't give any comment by Saturday evening, you can commit this.

Wouldn't this clamp threads with different priorities to the same index (tdq->tdq_ts_deq_off - 1)?

Is there any way that we can ensure tdq_ts_deq_off is always behind tdq_ts_off + MODULO and replace the whole thing as MPASS() instead?

Wouldn't this clamp threads with different priorities to the same index (tdq->tdq_ts_deq_off - 1)?

Is there any way that we can ensure tdq_ts_deq_off is always behind tdq_ts_off + MODULO and replace the whole thing as MPASS() instead?

Forget what I said above, we cannot do that under current design. I think clamping is fine if 1) it only happens to a few lowest priorities and 2) this situation doesn't happen often.

I think the current runq design is good for 4BSD, but it sometimes fails to address cases like this for ULE. A future improvement can be making the circular queue long enough so this doesn't happen, but it requires refactoring runq code as well both on 4BSD and ULE side.

Hence, LGTM:)