summaryrefslogtreecommitdiff
path: root/kern/priority.c
diff options
context:
space:
mode:
Diffstat (limited to 'kern/priority.c')
-rw-r--r--kern/priority.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/kern/priority.c b/kern/priority.c
new file mode 100644
index 0000000..f9a4091
--- /dev/null
+++ b/kern/priority.c
@@ -0,0 +1,225 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: clock_prim.c
+ * Author: Avadis Tevanian, Jr.
+ * Date: 1986
+ *
+ * Clock primitives.
+ */
+
+#include <cpus.h>
+
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/machine.h>
+#include <kern/host.h>
+#include <kern/mach_param.h>
+#include <kern/sched.h>
+#include <kern/thread.h>
+#include <kern/processor.h>
+#include <kern/timer.h>
+#include <kern/time_out.h>
+#include <kern/time_stamp.h>
+#include <machine/machspl.h>
+
+
+
+/*
+ * USAGE_THRESHOLD is the amount by which usage must change to
+ * cause a priority shift that moves a thread between run queues.
+ */
+
+#ifdef PRI_SHIFT_2
+#if PRI_SHIFT_2 > 0
+#define USAGE_THRESHOLD (((1 << PRI_SHIFT) + (1 << PRI_SHIFT_2)) << (2 + SCHED_SHIFT))
+#else /* PRI_SHIFT_2 > 0 */
+#define USAGE_THRESHOLD (((1 << PRI_SHIFT) - (1 << -(PRI_SHIFT_2))) << (2 + SCHED_SHIFT))
+#endif /* PRI_SHIFT_2 > 0 */
+#else /* PRI_SHIFT_2 */
+#define USAGE_THRESHOLD (1 << (PRI_SHIFT + 2 + SCHED_SHIFT))
+#endif /* PRI_SHIFT_2 */
+
+/*
+ * thread_quantum_update:
+ *
+ * Recalculate the quantum and priority for a thread.
+ * The number of ticks that has elapsed since we were last called
+ * is passed as "nticks."
+ *
+ * Called only from clock_interrupt().
+ */
+
+void thread_quantum_update(mycpu, thread, nticks, state)
+ register int mycpu;
+ register thread_t thread;
+ int nticks;
+ int state;
+{
+ register int quantum;
+ register processor_t myprocessor;
+#if NCPUS > 1
+ register processor_set_t pset;
+#endif
+ spl_t s;
+
+ myprocessor = cpu_to_processor(mycpu);
+#if NCPUS > 1
+ pset = myprocessor->processor_set;
+ if (pset == 0) {
+ /*
+ * Processor is being reassigned.
+ * Should rewrite processor assignment code to
+ * block clock interrupts.
+ */
+ return;
+ }
+#endif /* NCPUS > 1 */
+
+ /*
+ * Account for thread's utilization of these ticks.
+ * This assumes that there is *always* a current thread.
+ * When the processor is idle, it should be the idle thread.
+ */
+
+ /*
+ * Update set_quantum and calculate the current quantum.
+ */
+#if NCPUS > 1
+ pset->set_quantum = pset->machine_quantum[
+ ((pset->runq.count > pset->processor_count) ?
+ pset->processor_count : pset->runq.count)];
+
+ if (myprocessor->runq.count != 0)
+ quantum = min_quantum;
+ else
+ quantum = pset->set_quantum;
+#else /* NCPUS > 1 */
+ quantum = min_quantum;
+ default_pset.set_quantum = quantum;
+#endif /* NCPUS > 1 */
+
+ /*
+ * Now recompute the priority of the thread if appropriate.
+ */
+
+ if (state != CPU_STATE_IDLE) {
+ myprocessor->quantum -= nticks;
+#if NCPUS > 1
+ /*
+ * Runtime quantum adjustment. Use quantum_adj_index
+ * to avoid synchronizing quantum expirations.
+ */
+ if ((quantum != myprocessor->last_quantum) &&
+ (pset->processor_count > 1)) {
+ myprocessor->last_quantum = quantum;
+ simple_lock(&pset->quantum_adj_lock);
+ quantum = min_quantum + (pset->quantum_adj_index *
+ (quantum - min_quantum)) /
+ (pset->processor_count - 1);
+ if (++(pset->quantum_adj_index) >=
+ pset->processor_count)
+ pset->quantum_adj_index = 0;
+ simple_unlock(&pset->quantum_adj_lock);
+ }
+#endif /* NCPUS > 1 */
+ if (myprocessor->quantum <= 0) {
+ s = splsched();
+ thread_lock(thread);
+ if (thread->sched_stamp != sched_tick) {
+ update_priority(thread);
+ }
+ else {
+ if (
+#if MACH_FIXPRI
+ (thread->policy == POLICY_TIMESHARE) &&
+#endif /* MACH_FIXPRI */
+ (thread->depress_priority < 0)) {
+ thread_timer_delta(thread);
+ thread->sched_usage +=
+ thread->sched_delta;
+ thread->sched_delta = 0;
+ compute_my_priority(thread);
+ }
+ }
+ thread_unlock(thread);
+ (void) splx(s);
+ /*
+ * This quantum is up, give this thread another.
+ */
+ myprocessor->first_quantum = FALSE;
+#if MACH_FIXPRI
+ if (thread->policy == POLICY_TIMESHARE) {
+#endif /* MACH_FIXPRI */
+ myprocessor->quantum += quantum;
+#if MACH_FIXPRI
+ }
+ else {
+ /*
+ * Fixed priority has per-thread quantum.
+ *
+ */
+ myprocessor->quantum += thread->sched_data;
+ }
+#endif /* MACH_FIXPRI */
+ }
+ /*
+ * Recompute priority if appropriate.
+ */
+ else {
+ s = splsched();
+ thread_lock(thread);
+ if (thread->sched_stamp != sched_tick) {
+ update_priority(thread);
+ }
+ else {
+ if (
+#if MACH_FIXPRI
+ (thread->policy == POLICY_TIMESHARE) &&
+#endif /* MACH_FIXPRI */
+ (thread->depress_priority < 0)) {
+ thread_timer_delta(thread);
+ if (thread->sched_delta >= USAGE_THRESHOLD) {
+ thread->sched_usage +=
+ thread->sched_delta;
+ thread->sched_delta = 0;
+ compute_my_priority(thread);
+ }
+ }
+ }
+ thread_unlock(thread);
+ (void) splx(s);
+ }
+ /*
+ * Check for and schedule ast if needed.
+ */
+ ast_check();
+ }
+}
+