|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University. ! 4: * Copyright (c) 1993,1994 The University of Utah and ! 5: * the Computer Systems Laboratory (CSL). ! 6: * All rights reserved. ! 7: * ! 8: * Permission to use, copy, modify and distribute this software and its ! 9: * documentation is hereby granted, provided that both the copyright ! 10: * notice and this permission notice appear in all copies of the ! 11: * software, derivative works or modified versions, and any portions ! 12: * thereof, and that both notices appear in supporting documentation. ! 13: * ! 14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF ! 15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY ! 16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF ! 17: * THIS SOFTWARE. ! 18: * ! 19: * Carnegie Mellon requests users of this software to return to ! 20: * ! 21: * Software Distribution Coordinator or [email protected] ! 22: * School of Computer Science ! 23: * Carnegie Mellon University ! 24: * Pittsburgh PA 15213-3890 ! 25: * ! 26: * any improvements or extensions that they make and grant Carnegie Mellon ! 27: * the rights to redistribute these changes. ! 28: */ ! 29: /* ! 30: * File: clock_prim.c ! 31: * Author: Avadis Tevanian, Jr. ! 32: * Date: 1986 ! 33: * ! 34: * Clock primitives. ! 35: */ ! 36: ! 37: #include <cpus.h> ! 38: ! 39: #include <mach/boolean.h> ! 40: #include <mach/kern_return.h> ! 41: #include <mach/machine.h> ! 42: #include <kern/host.h> ! 43: #include <kern/mach_param.h> ! 44: #include <kern/sched.h> ! 45: #include <kern/thread.h> ! 46: #include <kern/processor.h> ! 47: #include <kern/timer.h> ! 48: #include <kern/time_out.h> ! 49: #include <kern/time_stamp.h> ! 50: #include <machine/machspl.h> ! 51: ! 52: ! 53: ! 54: /* ! 55: * USAGE_THRESHOLD is the amount by which usage must change to ! 56: * cause a priority shift that moves a thread between run queues. ! 57: */ ! 58: ! 59: #ifdef PRI_SHIFT_2 ! 60: #if PRI_SHIFT_2 > 0 ! 61: #define USAGE_THRESHOLD (((1 << PRI_SHIFT) + (1 << PRI_SHIFT_2)) << (2 + SCHED_SHIFT)) ! 62: #else /* PRI_SHIFT_2 > 0 */ ! 63: #define USAGE_THRESHOLD (((1 << PRI_SHIFT) - (1 << -(PRI_SHIFT_2))) << (2 + SCHED_SHIFT)) ! 64: #endif /* PRI_SHIFT_2 > 0 */ ! 65: #else /* PRI_SHIFT_2 */ ! 66: #define USAGE_THRESHOLD (1 << (PRI_SHIFT + 2 + SCHED_SHIFT)) ! 67: #endif /* PRI_SHIFT_2 */ ! 68: ! 69: /* ! 70: * thread_quantum_update: ! 71: * ! 72: * Recalculate the quantum and priority for a thread. ! 73: * The number of ticks that has elapsed since we were last called ! 74: * is passed as "nticks." ! 75: * ! 76: * Called only from clock_interrupt(). ! 77: */ ! 78: ! 79: void thread_quantum_update(mycpu, thread, nticks, state) ! 80: register int mycpu; ! 81: register thread_t thread; ! 82: int nticks; ! 83: int state; ! 84: { ! 85: register int quantum; ! 86: register processor_t myprocessor; ! 87: #if NCPUS > 1 ! 88: register processor_set_t pset; ! 89: #endif ! 90: spl_t s; ! 91: ! 92: myprocessor = cpu_to_processor(mycpu); ! 93: #if NCPUS > 1 ! 94: pset = myprocessor->processor_set; ! 95: if (pset == 0) { ! 96: /* ! 97: * Processor is being reassigned. ! 98: * Should rewrite processor assignment code to ! 99: * block clock interrupts. ! 100: */ ! 101: return; ! 102: } ! 103: #endif /* NCPUS > 1 */ ! 104: ! 105: /* ! 106: * Account for thread's utilization of these ticks. ! 107: * This assumes that there is *always* a current thread. ! 108: * When the processor is idle, it should be the idle thread. ! 109: */ ! 110: ! 111: /* ! 112: * Update set_quantum and calculate the current quantum. ! 113: */ ! 114: #if NCPUS > 1 ! 115: pset->set_quantum = pset->machine_quantum[ ! 116: ((pset->runq.count > pset->processor_count) ? ! 117: pset->processor_count : pset->runq.count)]; ! 118: ! 119: if (myprocessor->runq.count != 0) ! 120: quantum = min_quantum; ! 121: else ! 122: quantum = pset->set_quantum; ! 123: #else /* NCPUS > 1 */ ! 124: quantum = min_quantum; ! 125: default_pset.set_quantum = quantum; ! 126: #endif /* NCPUS > 1 */ ! 127: ! 128: /* ! 129: * Now recompute the priority of the thread if appropriate. ! 130: */ ! 131: ! 132: if (state != CPU_STATE_IDLE) { ! 133: myprocessor->quantum -= nticks; ! 134: #if NCPUS > 1 ! 135: /* ! 136: * Runtime quantum adjustment. Use quantum_adj_index ! 137: * to avoid synchronizing quantum expirations. ! 138: */ ! 139: if ((quantum != myprocessor->last_quantum) && ! 140: (pset->processor_count > 1)) { ! 141: myprocessor->last_quantum = quantum; ! 142: simple_lock(&pset->quantum_adj_lock); ! 143: quantum = min_quantum + (pset->quantum_adj_index * ! 144: (quantum - min_quantum)) / ! 145: (pset->processor_count - 1); ! 146: if (++(pset->quantum_adj_index) >= ! 147: pset->processor_count) ! 148: pset->quantum_adj_index = 0; ! 149: simple_unlock(&pset->quantum_adj_lock); ! 150: } ! 151: #endif /* NCPUS > 1 */ ! 152: if (myprocessor->quantum <= 0) { ! 153: s = splsched(); ! 154: thread_lock(thread); ! 155: if (thread->sched_stamp != sched_tick) { ! 156: update_priority(thread); ! 157: } ! 158: else { ! 159: if ( ! 160: #if MACH_FIXPRI ! 161: (thread->policy == POLICY_TIMESHARE) && ! 162: #endif /* MACH_FIXPRI */ ! 163: (thread->depress_priority < 0)) { ! 164: thread_timer_delta(thread); ! 165: thread->sched_usage += ! 166: thread->sched_delta; ! 167: thread->sched_delta = 0; ! 168: compute_my_priority(thread); ! 169: } ! 170: } ! 171: thread_unlock(thread); ! 172: (void) splx(s); ! 173: /* ! 174: * This quantum is up, give this thread another. ! 175: */ ! 176: myprocessor->first_quantum = FALSE; ! 177: #if MACH_FIXPRI ! 178: if (thread->policy == POLICY_TIMESHARE) { ! 179: #endif /* MACH_FIXPRI */ ! 180: myprocessor->quantum += quantum; ! 181: #if MACH_FIXPRI ! 182: } ! 183: else { ! 184: /* ! 185: * Fixed priority has per-thread quantum. ! 186: * ! 187: */ ! 188: myprocessor->quantum += thread->sched_data; ! 189: } ! 190: #endif /* MACH_FIXPRI */ ! 191: } ! 192: /* ! 193: * Recompute priority if appropriate. ! 194: */ ! 195: else { ! 196: s = splsched(); ! 197: thread_lock(thread); ! 198: if (thread->sched_stamp != sched_tick) { ! 199: update_priority(thread); ! 200: } ! 201: else { ! 202: if ( ! 203: #if MACH_FIXPRI ! 204: (thread->policy == POLICY_TIMESHARE) && ! 205: #endif /* MACH_FIXPRI */ ! 206: (thread->depress_priority < 0)) { ! 207: thread_timer_delta(thread); ! 208: if (thread->sched_delta >= USAGE_THRESHOLD) { ! 209: thread->sched_usage += ! 210: thread->sched_delta; ! 211: thread->sched_delta = 0; ! 212: compute_my_priority(thread); ! 213: } ! 214: } ! 215: } ! 216: thread_unlock(thread); ! 217: (void) splx(s); ! 218: } ! 219: /* ! 220: * Check for and schedule ast if needed. ! 221: */ ! 222: ast_check(); ! 223: } ! 224: } ! 225:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.