diff options
Diffstat (limited to 'sys/kern/kern_synch.c')
-rw-r--r-- | sys/kern/kern_synch.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 30a8bb3..a3e920d 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -413,9 +413,10 @@ mi_switch(int flags, struct thread *newtd) */ if (kdb_active) kdb_switch(); - if (flags & SW_VOL) + if (flags & SW_VOL) { td->td_ru.ru_nvcsw++; - else + td->td_swvoltick = ticks; + } else td->td_ru.ru_nivcsw++; #ifdef SCHED_STATS SCHED_STAT_INC(sched_switch_stats[flags & SW_TYPE_MASK]); @@ -538,6 +539,36 @@ synch_setup(void *dummy) loadav(NULL); } +int +should_yield(void) +{ + + return (ticks - curthread->td_swvoltick >= hogticks); +} + +void +maybe_yield(void) +{ + + if (should_yield()) + kern_yield(curthread->td_user_pri); +} + +void +kern_yield(int prio) +{ + struct thread *td; + + td = curthread; + DROP_GIANT(); + thread_lock(td); + if (prio >= 0) + sched_prio(td, prio); + mi_switch(SW_VOL | SWT_RELINQUISH, NULL); + thread_unlock(td); + PICKUP_GIANT(); +} + /* * General purpose yield system call. */ @@ -546,7 +577,8 @@ yield(struct thread *td, struct yield_args *uap) { thread_lock(td); - sched_prio(td, PRI_MAX_TIMESHARE); + if (PRI_BASE(td->td_pri_class) == PRI_TIMESHARE) + sched_prio(td, PRI_MAX_TIMESHARE); mi_switch(SW_VOL | SWT_RELINQUISH, NULL); thread_unlock(td); td->td_retval[0] = 0; |