Index: sys/kern/sched_ule.c =================================================================== --- sys/kern/sched_ule.c +++ sys/kern/sched_ule.c @@ -204,25 +204,24 @@ * due to rounding would be unacceptably high. * realstathz: stathz is sometimes 0 and run off of hz. * sched_slice: Runtime of each thread before rescheduling. - * preempt_thresh: Priority threshold for preemption and remote IPIs. */ static int sched_interact = SCHED_INTERACT_THRESH; static int tickincr = 8 << SCHED_TICK_SHIFT; static int realstathz = 127; /* reset during boot. */ static int sched_slice = 10; /* reset during boot. */ static int sched_slice_min = 1; /* reset during boot. */ -#ifdef PREEMPTION -#ifdef FULL_PREEMPTION -static int preempt_thresh = PRI_MAX_IDLE; -#else -static int preempt_thresh = PRI_MIN_KERN; -#endif -#else -static int preempt_thresh = 0; -#endif static int static_boost = PRI_MIN_BATCH; static int sched_idlespins = 10000; static int sched_idlespinthresh = -1; +#ifdef PREEMPTION +static bool preemption = true; +#else +static bool preemption = false; +#endif +static bool preempt_ithread; +static bool preempt_kthread; +static bool preempt_interactive; +static bool preempt_batch; /* * tdq - per processor runqs and statistics. All fields are protected by the @@ -422,33 +421,55 @@ sched_shouldpreempt(int pri, int cpri, int remote) { /* - * If the new priority is not better than the current priority there is - * nothing to do. + * If the new priority is not better than the current priority, then + * there is nothing to do. */ - if (pri >= cpri) + if (pri / RQ_PPQ >= cpri / RQ_PPQ ) return (0); - /* - * Always preempt idle. - */ + + /* Always preempt idle. */ if (cpri >= PRI_MIN_IDLE) return (1); - /* - * If preemption is disabled don't preempt others. - */ - if (preempt_thresh == 0) + + /* Check if preemption is completely disabled. */ + if (!preemption) return (0); + + KASSERT(pri < cpri, ("unexpected priorities for preemption policy")); + + /* Check if interrupt thread may be preempted. */ + if (!preempt_ithread && cpri <= PRI_MAX_ITHD) + return (0); + /* - * Preempt if we exceed the threshold. + * Interrupt thread may preempt any lower class thread. + * Real-time thread may preempt any same and lower class thread. */ - if (pri <= preempt_thresh) + if (pri <= PRI_MAX_REALTIME) return (1); - /* - * If we're interactive or better and there is non-interactive - * or worse running preempt only remote processors. - */ - if (remote && pri <= PRI_MAX_INTERACT && cpri > PRI_MAX_INTERACT) + + /* Check if kernel thread may be preempted. */ + if (!preempt_kthread && cpri <= PRI_MAX_KERN) + return (0); + + /* Kernel thread may preempt any other lower class thread. */ + if (pri <= PRI_MAX_KERN) return (1); - return (0); + + /* Check if interactive thread may be preempted. */ + if (!preempt_interactive && cpri <= PRI_MAX_INTERACT) + return (0); + + /* Interactive thread may preempt any other timeshare thread. */ + if (pri <= PRI_MAX_INTERACT) + return (1); + + /* Check if batch thread may be preempted. */ + if (!preempt_batch && cpri <= PRI_MAX_TIMESHARE) + return (0); + + /* Batch preemption is allowed, idle preemption is handled earlier. */ + return (1); } /* @@ -3041,9 +3062,19 @@ "Quantum for timeshare threads in stathz ticks"); SYSCTL_INT(_kern_sched, OID_AUTO, interact, CTLFLAG_RW, &sched_interact, 0, "Interactivity score threshold"); -SYSCTL_INT(_kern_sched, OID_AUTO, preempt_thresh, CTLFLAG_RW, - &preempt_thresh, 0, - "Maximal (lowest) priority for preemption"); +SYSCTL_BOOL(_kern_sched, OID_AUTO, preempt_ithread, CTLFLAG_RW, + &preempt_ithread, 0, + "Whether an interrupt thread may be preempted by another interrupt thread"); +SYSCTL_BOOL(_kern_sched, OID_AUTO, preempt_kthread, CTLFLAG_RW, + &preempt_kthread, 0, + "Whether a kernel thread may be preempted by another kernel thread"); +SYSCTL_BOOL(_kern_sched, OID_AUTO, preempt_interactive, CTLFLAG_RW, + &preempt_interactive, 0, + "Whether an interactive thread may be preempted by another " + "interactive thread"); +SYSCTL_BOOL(_kern_sched, OID_AUTO, preempt_batch, CTLFLAG_RW, + &preempt_batch, 0, + "Whether a batch thread may be preempted by another batch thread"); SYSCTL_INT(_kern_sched, OID_AUTO, static_boost, CTLFLAG_RW, &static_boost, 0, "Assign static kernel priorities to sleeping threads"); SYSCTL_INT(_kern_sched, OID_AUTO, idlespins, CTLFLAG_RW, &sched_idlespins, 0,