Summary: | [sched_ule] Not stealing process from loaded CPU | ||||||
---|---|---|---|---|---|---|---|
Product: | Base System | Reporter: | Mit Matelske <mit> | ||||
Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||
Status: | New --- | ||||||
Severity: | Affects Only Me | CC: | cem, eadler, emaste, fidaj, markj, truckman | ||||
Priority: | --- | Keywords: | patch | ||||
Version: | 11.1-RELEASE | ||||||
Hardware: | amd64 | ||||||
OS: | Any | ||||||
Attachments: |
|
Description
Mit Matelske
2018-05-08 18:13:04 UTC
Don, I've CC'ed you as you have previously had some interest in ULE. Feel free to un-CC if you're not interested :-). Thread stealing is only done in the CPU idle loop (or more recently, when ULE detects that the CPU is about to go idle). Since none of the CPUs is idle in this case, stealing will not happen. Setting kern.sched.steal_thresh=1 won't make a difference since the stuck thread raises the load to 2 on the CPU is where it is assigned. In theory sched_balance() should eventually move the stuck thread to the CPU is running "runOne", but it runs infrequently and if the destination CPU is chosen totally randomly, that could take a while. There could be an issue in how it chooses the destination CPU that prevents it from ever choosing the CPU where "runOne" is running ... Don- My problem is that once it is "stuck" I can stop the runOne script and free up the remaining CPU and the ifconfig process will remain on the busy CPU. The machine is sitting 12.5% idle but the process never migrates. The "top" snapshot I included shows this. Created attachment 193209 [details] fix sched_balance (In reply to Don Lewis from comment #2) Hmm, I think sched_balance() is actually busted: the initial call is performed while smp_started == 0, so balance_ticks is never set to a non-zero value. The attached patch seems to address that at least. (In reply to Mark Johnston from comment #4) Looks reasonable to me. (In reply to Mark Johnston from comment #4) That is, this is due to this PR? https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=223914 (In reply to Ivan Klymenko from comment #6) Could be, I'm hoping that the submitter tries applying the patch to see if the problem persists. I didn't realize a PR already existed for sched_balance(). I'll work on getting it fixed. Sorry for the delay! I tried the patch out and sched_balance_group now runs but the I can still get a process stuck in the RUN state on a busy CPU. FWIW, it doesn't seem like that mechanism ever moves processes. All my calls to tdq_move comes from the tdq_idled loop. I'm debugging why the process doesn't get moved now. Weird thing is other processes are successfully getting moved from the busy CPUs from the tdq_idled loop. Just not the stuck process. Don't know if this helps, but it seems like if I start another process, something triggers and it will move the stuck process and everything will run fine for awhile. Any clues from that? (In reply to Mit Matelske from comment #3) Hmn, the idle CPU should then be able to steal the stuck process. Maybe it is stuck in some state where migration is forbidden ... Looks like td_pinned gets set so the thread can't move from the busy processor. Not sure why that occasionally happens? (In reply to Mit Matelske from comment #10) The kernel stack of the thread will provide a clue, if you're able to obtain it. procstat -kk <pid> can grab the kernel stack of a running thread. # procstat -kk 1557 PID TID COMM TDNAME KSTACK 1557 100825 ifconfig - mi_switch+0xe5 critical_exit+0x7a ipi_bitmap_handler+0x79 ipi_intr_bitmap_handler_u+0x9c userland_sysctl+0x157 sys___sysctl+0x5f amd64_syscall+0x6c4 fast_syscall_common+0x106 I'm not able to reproduce this on HEAD. I'll try setting up an 11.1 VM for testing. I'm a bit confused by the repro. I presume the expected behaviour is that the ifconfig thread should be migrated to the CPU running "one". But in your sample "top" output, the last CPU is idle even though you're running "one" in a loop there - how can that be? In the top output, I had stopped the "one" program to show that even if the processor goes idle the ifconfig never gets migrated to 7. Sorry for the confusion. Is this reproducible on 12.2 or later? I think td_pinned is the problem. The thread can't move until that flag is cleared, and that can't happen until it is able to get some CPU cycles to get through the section of code that td_pinned is protecting. I can see how this could happen in the general case, but in this particular case how does the ifconfig thread manage to make enough progress to set td_pinned while competing with the hard realtime thread that is hogging the cpu? |