]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/sched_fixedpriority.c
xnu-1699.26.8.tar.gz
[apple/xnu.git] / osfmk / kern / sched_fixedpriority.c
CommitLineData
6d2010ae
A
1/*
2 * Copyright (c) 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include <mach/mach_types.h>
30#include <mach/machine.h>
31#include <mach/policy.h>
32#include <mach/sync_policy.h>
33#include <mach/thread_act.h>
34
35#include <machine/machine_routines.h>
36#include <machine/sched_param.h>
37#include <machine/machine_cpu.h>
38
39#include <kern/kern_types.h>
40#include <kern/clock.h>
41#include <kern/counters.h>
42#include <kern/cpu_number.h>
43#include <kern/cpu_data.h>
44#include <kern/debug.h>
45#include <kern/lock.h>
46#include <kern/macro_help.h>
47#include <kern/machine.h>
48#include <kern/misc_protos.h>
49#include <kern/processor.h>
50#include <kern/queue.h>
51#include <kern/sched.h>
52#include <kern/sched_prim.h>
53#include <kern/syscall_subr.h>
54#include <kern/task.h>
55#include <kern/thread.h>
56#include <kern/wait_queue.h>
57
58#include <vm/pmap.h>
59#include <vm/vm_kern.h>
60#include <vm/vm_map.h>
61
62#include <mach/sdt.h>
63
64#include <sys/kdebug.h>
65
66static void
67sched_fixedpriority_init(void);
68
69static void
70sched_fixedpriority_with_pset_runqueue_init(void);
71
72static void
73sched_fixedpriority_timebase_init(void);
74
75static void
76sched_fixedpriority_processor_init(processor_t processor);
77
78static void
79sched_fixedpriority_pset_init(processor_set_t pset);
80
81static void
82sched_fixedpriority_maintenance_continuation(void);
83
84static thread_t
85sched_fixedpriority_choose_thread(processor_t processor,
86 int priority);
87
88static thread_t
89sched_fixedpriority_steal_thread(processor_set_t pset);
90
91static void
92sched_fixedpriority_compute_priority(thread_t thread,
93 boolean_t override_depress);
94
95static processor_t
96sched_fixedpriority_choose_processor( processor_set_t pset,
97 processor_t processor,
98 thread_t thread);
99
100
101static boolean_t
102sched_fixedpriority_processor_enqueue(
103 processor_t processor,
104 thread_t thread,
105 integer_t options);
106
107static void
108sched_fixedpriority_processor_queue_shutdown(
109 processor_t processor);
110
111static boolean_t
112sched_fixedpriority_processor_queue_remove(
113 processor_t processor,
114 thread_t thread);
115
116static boolean_t
117sched_fixedpriority_processor_queue_empty(processor_t processor);
118
119static boolean_t
120sched_fixedpriority_processor_queue_has_priority(processor_t processor,
121 int priority,
122 boolean_t gte);
123
124static boolean_t
125sched_fixedpriority_priority_is_urgent(int priority);
126
127static ast_t
128sched_fixedpriority_processor_csw_check(processor_t processor);
129
130static uint32_t
131sched_fixedpriority_initial_quantum_size(thread_t thread);
132
133static sched_mode_t
134sched_fixedpriority_initial_thread_sched_mode(task_t parent_task);
135
136static boolean_t
137sched_fixedpriority_supports_timeshare_mode(void);
138
139static boolean_t
140sched_fixedpriority_can_update_priority(thread_t thread);
141
142static void
143sched_fixedpriority_update_priority(thread_t thread);
144
145static void
146sched_fixedpriority_lightweight_update_priority(thread_t thread);
147
148static void
149sched_fixedpriority_quantum_expire(thread_t thread);
150
151static boolean_t
152sched_fixedpriority_should_current_thread_rechoose_processor(processor_t processor);
153
154static int
155sched_fixedpriority_processor_runq_count(processor_t processor);
156
157static uint64_t
158sched_fixedpriority_processor_runq_stats_count_sum(processor_t processor);
159
160const struct sched_dispatch_table sched_fixedpriority_dispatch = {
161 sched_fixedpriority_init,
162 sched_fixedpriority_timebase_init,
163 sched_fixedpriority_processor_init,
164 sched_fixedpriority_pset_init,
165 sched_fixedpriority_maintenance_continuation,
166 sched_fixedpriority_choose_thread,
167 sched_fixedpriority_steal_thread,
168 sched_fixedpriority_compute_priority,
169 sched_fixedpriority_choose_processor,
170 sched_fixedpriority_processor_enqueue,
171 sched_fixedpriority_processor_queue_shutdown,
172 sched_fixedpriority_processor_queue_remove,
173 sched_fixedpriority_processor_queue_empty,
174 sched_fixedpriority_priority_is_urgent,
175 sched_fixedpriority_processor_csw_check,
176 sched_fixedpriority_processor_queue_has_priority,
177 sched_fixedpriority_initial_quantum_size,
178 sched_fixedpriority_initial_thread_sched_mode,
179 sched_fixedpriority_supports_timeshare_mode,
180 sched_fixedpriority_can_update_priority,
181 sched_fixedpriority_update_priority,
182 sched_fixedpriority_lightweight_update_priority,
183 sched_fixedpriority_quantum_expire,
184 sched_fixedpriority_should_current_thread_rechoose_processor,
185 sched_fixedpriority_processor_runq_count,
186 sched_fixedpriority_processor_runq_stats_count_sum,
187 sched_traditional_fairshare_init,
188 sched_traditional_fairshare_runq_count,
189 sched_traditional_fairshare_runq_stats_count_sum,
190 sched_traditional_fairshare_enqueue,
191 sched_traditional_fairshare_dequeue,
192 sched_traditional_fairshare_queue_remove,
193 TRUE /* direct_dispatch_to_idle_processors */
194};
195
196const struct sched_dispatch_table sched_fixedpriority_with_pset_runqueue_dispatch = {
197 sched_fixedpriority_with_pset_runqueue_init,
198 sched_fixedpriority_timebase_init,
199 sched_fixedpriority_processor_init,
200 sched_fixedpriority_pset_init,
201 sched_fixedpriority_maintenance_continuation,
202 sched_fixedpriority_choose_thread,
203 sched_fixedpriority_steal_thread,
204 sched_fixedpriority_compute_priority,
205 sched_fixedpriority_choose_processor,
206 sched_fixedpriority_processor_enqueue,
207 sched_fixedpriority_processor_queue_shutdown,
208 sched_fixedpriority_processor_queue_remove,
209 sched_fixedpriority_processor_queue_empty,
210 sched_fixedpriority_priority_is_urgent,
211 sched_fixedpriority_processor_csw_check,
212 sched_fixedpriority_processor_queue_has_priority,
213 sched_fixedpriority_initial_quantum_size,
214 sched_fixedpriority_initial_thread_sched_mode,
215 sched_fixedpriority_supports_timeshare_mode,
216 sched_fixedpriority_can_update_priority,
217 sched_fixedpriority_update_priority,
218 sched_fixedpriority_lightweight_update_priority,
219 sched_fixedpriority_quantum_expire,
220 sched_fixedpriority_should_current_thread_rechoose_processor,
221 sched_fixedpriority_processor_runq_count,
222 sched_fixedpriority_processor_runq_stats_count_sum,
223 sched_traditional_fairshare_init,
224 sched_traditional_fairshare_runq_count,
225 sched_traditional_fairshare_runq_stats_count_sum,
226 sched_traditional_fairshare_enqueue,
227 sched_traditional_fairshare_dequeue,
228 sched_traditional_fairshare_queue_remove,
229 FALSE /* direct_dispatch_to_idle_processors */
230};
231
232extern int max_unsafe_quanta;
233
234#define SCHED_FIXEDPRIORITY_DEFAULT_QUANTUM 5 /* in ms */
235static uint32_t sched_fixedpriority_quantum_ms = SCHED_FIXEDPRIORITY_DEFAULT_QUANTUM;
236static uint32_t sched_fixedpriority_quantum;
237
238#define SCHED_FIXEDPRIORITY_DEFAULT_FAIRSHARE_MINIMUM_BLOCK_TIME 100 /* ms */
239static uint32_t fairshare_minimum_blocked_time_ms = SCHED_FIXEDPRIORITY_DEFAULT_FAIRSHARE_MINIMUM_BLOCK_TIME;
240static uint32_t fairshare_minimum_blocked_time;
241
242static uint32_t sched_fixedpriority_tick;
243static uint64_t sched_fixedpriority_tick_deadline;
244extern uint32_t grrr_rescale_tick;
245
246static boolean_t sched_fixedpriority_use_pset_runqueue = FALSE;
247
248__attribute__((always_inline))
249static inline run_queue_t runq_for_processor(processor_t processor)
250{
251 if (sched_fixedpriority_use_pset_runqueue)
252 return &processor->processor_set->pset_runq;
253 else
254 return &processor->runq;
255}
256
257__attribute__((always_inline))
258static inline void runq_consider_incr_bound_count(processor_t processor, thread_t thread)
259{
260 if (thread->bound_processor == PROCESSOR_NULL)
261 return;
262
263 assert(thread->bound_processor == processor);
264
265 if (sched_fixedpriority_use_pset_runqueue)
266 processor->processor_set->pset_runq_bound_count++;
267
268 processor->runq_bound_count++;
269}
270
271__attribute__((always_inline))
272static inline void runq_consider_decr_bound_count(processor_t processor, thread_t thread)
273{
274 if (thread->bound_processor == PROCESSOR_NULL)
275 return;
276
277 assert(thread->bound_processor == processor);
278
279 if (sched_fixedpriority_use_pset_runqueue)
280 processor->processor_set->pset_runq_bound_count--;
281
282 processor->runq_bound_count--;
283}
284
285static void
286sched_fixedpriority_init(void)
287{
288 if (!PE_parse_boot_argn("fixedpriority_quantum", &sched_fixedpriority_quantum_ms, sizeof (sched_fixedpriority_quantum_ms))) {
289 sched_fixedpriority_quantum_ms = SCHED_FIXEDPRIORITY_DEFAULT_QUANTUM;
290 }
291
292 if (sched_fixedpriority_quantum_ms < 1)
293 sched_fixedpriority_quantum_ms = SCHED_FIXEDPRIORITY_DEFAULT_QUANTUM;
294
295 printf("standard fixed priority timeslicing quantum is %u ms\n", sched_fixedpriority_quantum_ms);
296}
297
298static void
299sched_fixedpriority_with_pset_runqueue_init(void)
300{
301 sched_fixedpriority_init();
302 sched_fixedpriority_use_pset_runqueue = TRUE;
303}
304
305static void
306sched_fixedpriority_timebase_init(void)
307{
308 uint64_t abstime;
309
310 /* standard timeslicing quantum */
311 clock_interval_to_absolutetime_interval(
312 sched_fixedpriority_quantum_ms, NSEC_PER_MSEC, &abstime);
313 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
314 sched_fixedpriority_quantum = (uint32_t)abstime;
315
316 thread_depress_time = 1 * sched_fixedpriority_quantum;
317 default_timeshare_computation = sched_fixedpriority_quantum / 2;
318 default_timeshare_constraint = sched_fixedpriority_quantum;
319
320 max_unsafe_computation = max_unsafe_quanta * sched_fixedpriority_quantum;
321 sched_safe_duration = 2 * max_unsafe_quanta * sched_fixedpriority_quantum;
322
323 if (!PE_parse_boot_argn("fairshare_minblockedtime", &fairshare_minimum_blocked_time_ms, sizeof (fairshare_minimum_blocked_time_ms))) {
324 fairshare_minimum_blocked_time_ms = SCHED_FIXEDPRIORITY_DEFAULT_FAIRSHARE_MINIMUM_BLOCK_TIME;
325 }
326
327 clock_interval_to_absolutetime_interval(
328 fairshare_minimum_blocked_time_ms, NSEC_PER_MSEC, &abstime);
329
330 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
331 fairshare_minimum_blocked_time = (uint32_t)abstime;
332}
333
334static void
335sched_fixedpriority_processor_init(processor_t processor)
336{
337 if (!sched_fixedpriority_use_pset_runqueue) {
338 run_queue_init(&processor->runq);
339 }
340 processor->runq_bound_count = 0;
341}
342
343static void
344sched_fixedpriority_pset_init(processor_set_t pset)
345{
346 if (sched_fixedpriority_use_pset_runqueue) {
347 run_queue_init(&pset->pset_runq);
348 }
349 pset->pset_runq_bound_count = 0;
350}
351
352
353static void
354sched_fixedpriority_maintenance_continuation(void)
355{
356 uint64_t abstime = mach_absolute_time();
357
358 sched_fixedpriority_tick++;
359 grrr_rescale_tick++;
360
361 /*
362 * Compute various averages.
363 */
364 compute_averages();
365
366 if (sched_fixedpriority_tick_deadline == 0)
367 sched_fixedpriority_tick_deadline = abstime;
368
369 clock_deadline_for_periodic_event(10*sched_one_second_interval, abstime,
370 &sched_fixedpriority_tick_deadline);
371
372 assert_wait_deadline((event_t)sched_fixedpriority_maintenance_continuation, THREAD_UNINT, sched_fixedpriority_tick_deadline);
373 thread_block((thread_continue_t)sched_fixedpriority_maintenance_continuation);
374 /*NOTREACHED*/
375}
376
377
378static thread_t
379sched_fixedpriority_choose_thread(processor_t processor,
380 int priority)
381{
382 thread_t thread;
383
384 thread = choose_thread(processor, runq_for_processor(processor), priority);
385 if (thread != THREAD_NULL) {
386 runq_consider_decr_bound_count(processor, thread);
387 }
388
389 return thread;
390}
391
392static thread_t
393sched_fixedpriority_steal_thread(processor_set_t pset)
394{
395 pset_unlock(pset);
396
397 return (THREAD_NULL);
398
399}
400
401static void
402sched_fixedpriority_compute_priority(thread_t thread,
403 boolean_t override_depress)
404{
405 /* Reset current priority to base priority */
406 if ( !(thread->sched_flags & TH_SFLAG_PROMOTED) &&
407 (!(thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) ||
408 override_depress ) ) {
409 set_sched_pri(thread, thread->priority);
410 }
411}
412
413static processor_t
414sched_fixedpriority_choose_processor( processor_set_t pset,
415 processor_t processor,
416 thread_t thread)
417{
418 return choose_processor(pset, processor, thread);
419}
420static boolean_t
421sched_fixedpriority_processor_enqueue(
422 processor_t processor,
423 thread_t thread,
424 integer_t options)
425{
426 run_queue_t rq = runq_for_processor(processor);
427 boolean_t result;
428
429 result = run_queue_enqueue(rq, thread, options);
430 thread->runq = processor;
431 runq_consider_incr_bound_count(processor, thread);
432
433 return (result);
434}
435
436static void
437sched_fixedpriority_processor_queue_shutdown(
438 processor_t processor)
439{
440 processor_set_t pset = processor->processor_set;
441 thread_t thread;
442 queue_head_t tqueue, bqueue;
443
444 queue_init(&tqueue);
445 queue_init(&bqueue);
446
447 while ((thread = sched_fixedpriority_choose_thread(processor, IDLEPRI)) != THREAD_NULL) {
448 if (thread->bound_processor == PROCESSOR_NULL) {
449 enqueue_tail(&tqueue, (queue_entry_t)thread);
450 } else {
451 enqueue_tail(&bqueue, (queue_entry_t)thread);
452 }
453 }
454
455 while ((thread = (thread_t)dequeue_head(&bqueue)) != THREAD_NULL) {
456 sched_fixedpriority_processor_enqueue(processor, thread, SCHED_TAILQ);
457 }
458
459 pset_unlock(pset);
460
461 while ((thread = (thread_t)dequeue_head(&tqueue)) != THREAD_NULL) {
462 thread_lock(thread);
463
464 thread_setrun(thread, SCHED_TAILQ);
465
466 thread_unlock(thread);
467 }
468}
469
470static boolean_t
471sched_fixedpriority_processor_queue_remove(
472 processor_t processor,
473 thread_t thread)
474{
475 void * rqlock;
476 run_queue_t rq;
477
478 rqlock = &processor->processor_set->sched_lock;
479 rq = runq_for_processor(processor);
480
481 simple_lock(rqlock);
482 if (processor == thread->runq) {
483 /*
484 * Thread is on a run queue and we have a lock on
485 * that run queue.
486 */
487 runq_consider_decr_bound_count(processor, thread);
488 run_queue_remove(rq, thread);
489 }
490 else {
491 /*
492 * The thread left the run queue before we could
493 * lock the run queue.
494 */
495 assert(thread->runq == PROCESSOR_NULL);
496 processor = PROCESSOR_NULL;
497 }
498
499 simple_unlock(rqlock);
500
501 return (processor != PROCESSOR_NULL);
502}
503
504static boolean_t
505sched_fixedpriority_processor_queue_empty(processor_t processor)
506{
507 /*
508 * See sched_traditional_with_pset_runqueue_processor_queue_empty
509 * for algorithm
510 */
511 int count = runq_for_processor(processor)->count;
512
513 if (sched_fixedpriority_use_pset_runqueue) {
514 processor_set_t pset = processor->processor_set;
515
516 count -= pset->pset_runq_bound_count;
517 count += processor->runq_bound_count;
518 }
519
520 return count == 0;
521}
522
523static boolean_t
524sched_fixedpriority_processor_queue_has_priority(processor_t processor,
525 int priority,
526 boolean_t gte)
527{
528 if (gte)
529 return runq_for_processor(processor)->highq >= priority;
530 else
531 return runq_for_processor(processor)->highq > priority;
532}
533
534/* Implement sched_preempt_pri in code */
535static boolean_t
536sched_fixedpriority_priority_is_urgent(int priority)
537{
538 if (priority <= BASEPRI_FOREGROUND)
539 return FALSE;
540
541 if (priority < MINPRI_KERNEL)
542 return TRUE;
543
544 if (priority >= BASEPRI_PREEMPT)
545 return TRUE;
546
547 return FALSE;
548}
549
550static ast_t
551sched_fixedpriority_processor_csw_check(processor_t processor)
552{
553 run_queue_t runq;
554
555 runq = runq_for_processor(processor);
556 if (runq->highq > processor->current_pri) {
557 if (runq->urgency > 0)
558 return (AST_PREEMPT | AST_URGENT);
559
560 if (processor->active_thread && thread_eager_preemption(processor->active_thread))
561 return (AST_PREEMPT | AST_URGENT);
562
563 return AST_PREEMPT;
564 } else if (processor->current_thmode == TH_MODE_FAIRSHARE) {
565 if (!sched_fixedpriority_processor_queue_empty(processor)) {
566 /* Allow queued threads to run if the current thread got demoted to fairshare */
567 return (AST_PREEMPT | AST_URGENT);
568 } else if ((!first_timeslice(processor)) && SCHED(fairshare_runq_count)() > 0) {
569 /* Allow other fairshare threads to run */
570 return AST_PREEMPT | AST_URGENT;
571 }
572 }
573
574 return AST_NONE;
575}
576
577static uint32_t
578sched_fixedpriority_initial_quantum_size(thread_t thread __unused)
579{
580 return sched_fixedpriority_quantum;
581}
582
583static sched_mode_t
584sched_fixedpriority_initial_thread_sched_mode(task_t parent_task)
585{
586 if (parent_task == kernel_task)
587 return TH_MODE_FIXED;
588 else
589 return TH_MODE_TIMESHARE;
590}
591
592static boolean_t
593sched_fixedpriority_supports_timeshare_mode(void)
594{
595 return TRUE;
596}
597
598static boolean_t
599sched_fixedpriority_can_update_priority(thread_t thread __unused)
600{
601 return ((thread->sched_flags & TH_SFLAG_PRI_UPDATE) == 0);
602}
603
604static void
605sched_fixedpriority_update_priority(thread_t thread)
606{
607 uint64_t current_time = mach_absolute_time();
608
609 thread->sched_flags |= TH_SFLAG_PRI_UPDATE;
610
611 if (thread->sched_flags & TH_SFLAG_FAIRSHARE_TRIPPED) {
612
613 /*
614 * Make sure we've waited fairshare_minimum_blocked_time both from the time
615 * we were throttled into the fairshare band, and the last time
616 * we ran.
617 */
618 if (current_time >= thread->last_run_time + fairshare_minimum_blocked_time) {
619
620 boolean_t removed = thread_run_queue_remove(thread);
621
622 thread->sched_flags &= ~TH_SFLAG_FAIRSHARE_TRIPPED;
623 thread->sched_mode = thread->saved_mode;
624 thread->saved_mode = TH_MODE_NONE;
625
626 if (removed)
627 thread_setrun(thread, SCHED_TAILQ);
628
629 KERNEL_DEBUG_CONSTANT1(
630 MACHDBG_CODE(DBG_MACH_SCHED,MACH_FAIRSHARE_EXIT) | DBG_FUNC_NONE, (uint32_t)(thread->last_run_time & 0xFFFFFFFF), (uint32_t)(thread->last_run_time >> 32), (uint32_t)(current_time & 0xFFFFFFFF), (uint32_t)(current_time >> 32), thread_tid(thread));
631
632 }
633 } else if ((thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) && (thread->bound_processor == PROCESSOR_NULL)) {
634 boolean_t removed = thread_run_queue_remove(thread);
635
636 thread->sched_flags |= TH_SFLAG_FAIRSHARE_TRIPPED;
637 thread->saved_mode = thread->sched_mode;
638 thread->sched_mode = TH_MODE_FAIRSHARE;
639
640 thread->last_quantum_refill_time = thread->last_run_time - 2 * sched_fixedpriority_quantum - 1;
641
642 if (removed)
643 thread_setrun(thread, SCHED_TAILQ);
644
645 KERNEL_DEBUG_CONSTANT(
646 MACHDBG_CODE(DBG_MACH_SCHED,MACH_FAIRSHARE_ENTER) | DBG_FUNC_NONE, (uintptr_t)thread_tid(thread), 0xFFFFFFFF, 0, 0, 0);
647
648 }
649
650 /*
651 * Check for fail-safe release.
652 */
653 if ( (thread->sched_flags & TH_SFLAG_FAILSAFE) &&
654 current_time >= thread->safe_release ) {
655
656
657 thread->sched_flags &= ~TH_SFLAG_FAILSAFE;
658
659 if (!(thread->sched_flags & TH_SFLAG_DEMOTED_MASK)) {
660 /* Restore to previous */
661
662 thread->sched_mode = thread->saved_mode;
663 thread->saved_mode = TH_MODE_NONE;
664
665 if (thread->sched_mode == TH_MODE_REALTIME) {
666 thread->priority = BASEPRI_RTQUEUES;
667
668 }
669
670 if (!(thread->sched_flags & TH_SFLAG_DEPRESSED_MASK))
671 set_sched_pri(thread, thread->priority);
672 }
673 }
674
675 thread->sched_flags &= ~TH_SFLAG_PRI_UPDATE;
676 return;
677}
678
679static void
680sched_fixedpriority_lightweight_update_priority(thread_t thread __unused)
681{
682 return;
683}
684
685static void
686sched_fixedpriority_quantum_expire(
687 thread_t thread)
688{
689 /* Put thread into fairshare class, core scheduler will manage runqueue */
690 if ((thread->sched_mode == TH_MODE_TIMESHARE) && (thread->task != kernel_task) && !(thread->sched_flags & TH_SFLAG_DEMOTED_MASK)) {
691 uint64_t elapsed = thread->last_run_time - thread->last_quantum_refill_time;
692
693 /* If we managed to use our quantum in less than 2*quantum wall clock time,
694 * we are considered CPU bound and eligible for demotion. Since the quantum
695 * is reset when thread_unblock() is called, we are only really considering
696 * threads that elongate their execution time due to preemption.
697 */
698 if ((elapsed < 2 * sched_fixedpriority_quantum) && (thread->bound_processor == PROCESSOR_NULL)) {
699
700 thread->saved_mode = thread->sched_mode;
701 thread->sched_mode = TH_MODE_FAIRSHARE;
702 thread->sched_flags |= TH_SFLAG_FAIRSHARE_TRIPPED;
703 KERNEL_DEBUG_CONSTANT(
704 MACHDBG_CODE(DBG_MACH_SCHED,MACH_FAIRSHARE_ENTER) | DBG_FUNC_NONE, (uintptr_t)thread_tid(thread), (uint32_t)(elapsed & 0xFFFFFFFF), (uint32_t)(elapsed >> 32), 0, 0);
705 }
706 }
707}
708
709
710static boolean_t
711sched_fixedpriority_should_current_thread_rechoose_processor(processor_t processor __unused)
712{
713 return (TRUE);
714}
715
716
717static int
718sched_fixedpriority_processor_runq_count(processor_t processor)
719{
720 return runq_for_processor(processor)->count;
721}
722
723static uint64_t
724sched_fixedpriority_processor_runq_stats_count_sum(processor_t processor)
725{
726 return runq_for_processor(processor)->runq_stats.count_sum;
727}