* The machine independent parts of context switching. * * The thread lock is required on entry and is no longer held on return. */
| 485 | * The thread lock is required on entry and is no longer held on return. |
| 486 | */ |
| 487 | void |
| 488 | mi_switch(int flags) |
| 489 | { |
| 490 | uint64_t runtime, new_switchtime; |
| 491 | struct thread *td; |
| 492 | |
| 493 | td = curthread; /* XXX */ |
| 494 | THREAD_LOCK_ASSERT(td, MA_OWNED | MA_NOTRECURSED); |
| 495 | KASSERT(!TD_ON_RUNQ(td), ("mi_switch: called by old code")); |
| 496 | #ifdef INVARIANTS |
| 497 | if (!TD_ON_LOCK(td) && !TD_IS_RUNNING(td)) |
| 498 | mtx_assert(&Giant, MA_NOTOWNED); |
| 499 | #endif |
| 500 | KASSERT(td->td_critnest == 1 || KERNEL_PANICKED(), |
| 501 | ("mi_switch: switch in a critical section")); |
| 502 | KASSERT((flags & (SW_INVOL | SW_VOL)) != 0, |
| 503 | ("mi_switch: switch must be voluntary or involuntary")); |
| 504 | |
| 505 | /* |
| 506 | * Don't perform context switches from the debugger. |
| 507 | */ |
| 508 | if (kdb_active) |
| 509 | kdb_switch(); |
| 510 | if (SCHEDULER_STOPPED_TD(td)) |
| 511 | return; |
| 512 | if (flags & SW_VOL) { |
| 513 | td->td_ru.ru_nvcsw++; |
| 514 | td->td_swvoltick = ticks; |
| 515 | } else { |
| 516 | td->td_ru.ru_nivcsw++; |
| 517 | td->td_swinvoltick = ticks; |
| 518 | } |
| 519 | #ifdef SCHED_STATS |
| 520 | SCHED_STAT_INC(sched_switch_stats[flags & SW_TYPE_MASK]); |
| 521 | #endif |
| 522 | /* |
| 523 | * Compute the amount of time during which the current |
| 524 | * thread was running, and add that to its total so far. |
| 525 | */ |
| 526 | new_switchtime = cpu_ticks(); |
| 527 | runtime = new_switchtime - PCPU_GET(switchtime); |
| 528 | td->td_runtime += runtime; |
| 529 | td->td_incruntime += runtime; |
| 530 | PCPU_SET(switchtime, new_switchtime); |
| 531 | td->td_generation++; /* bump preempt-detect counter */ |
| 532 | VM_CNT_INC(v_swtch); |
| 533 | PCPU_SET(switchticks, ticks); |
| 534 | CTR4(KTR_PROC, "mi_switch: old thread %ld (td_sched %p, pid %ld, %s)", |
| 535 | td->td_tid, td_get_sched(td), td->td_proc->p_pid, td->td_name); |
| 536 | #ifdef KDTRACE_HOOKS |
| 537 | if (SDT_PROBES_ENABLED() && |
| 538 | ((flags & SW_PREEMPT) != 0 || ((flags & SW_INVOL) != 0 && |
| 539 | (flags & SW_TYPE_MASK) == SWT_NEEDRESCHED))) |
| 540 | SDT_PROBE0(sched, , , preempt); |
| 541 | #endif |
| 542 | sched_switch(td, flags); |
| 543 | CTR4(KTR_PROC, "mi_switch: new thread %ld (td_sched %p, pid %ld, %s)", |
| 544 | td->td_tid, td_get_sched(td), td->td_proc->p_pid, td->td_name); |
no test coverage detected