|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * ! 28: * File: kern/thread_swap.c ! 29: * Author: Avadis Tevanian, Jr. ! 30: * Date: 1987 ! 31: * ! 32: * Mach thread swapper: ! 33: * Find idle threads to swap, freeing up kernel stack resources ! 34: * at the expense of allowing them to execute. ! 35: * ! 36: * Swap in threads that need to be run. This is done here ! 37: * by the swapper thread since it cannot be done (in general) ! 38: * when the kernel tries to place a thread on a run queue. ! 39: * ! 40: * Note: The act of swapping a thread in Mach does not mean that ! 41: * its memory gets forcibly swapped to secondary storage. The memory ! 42: * for the task corresponding to a swapped thread is paged out ! 43: * through the normal paging mechanism. ! 44: * ! 45: */ ! 46: ! 47: #include <ipc/ipc_kmsg.h> ! 48: #include <kern/counters.h> ! 49: #include <kern/thread.h> ! 50: #include <kern/lock.h> ! 51: #include <vm/vm_map.h> ! 52: #include <vm/vm_kern.h> ! 53: #include <mach/vm_param.h> ! 54: #include <kern/sched_prim.h> ! 55: #include <kern/processor.h> ! 56: #include <kern/thread_swap.h> ! 57: #include <machine/machspl.h> /* for splsched */ ! 58: ! 59: ! 60: ! 61: queue_head_t swapin_queue; ! 62: decl_simple_lock_data(, swapper_lock_data) ! 63: ! 64: #define swapper_lock() simple_lock(&swapper_lock_data) ! 65: #define swapper_unlock() simple_unlock(&swapper_lock_data) ! 66: ! 67: /* ! 68: * swapper_init: [exported] ! 69: * ! 70: * Initialize the swapper module. ! 71: */ ! 72: void swapper_init() ! 73: { ! 74: queue_init(&swapin_queue); ! 75: simple_lock_init(&swapper_lock_data); ! 76: } ! 77: ! 78: /* ! 79: * thread_swapin: [exported] ! 80: * ! 81: * Place the specified thread in the list of threads to swapin. It ! 82: * is assumed that the thread is locked, therefore we are at splsched. ! 83: * ! 84: * We don't bother with stack_alloc_try to optimize swapin; ! 85: * our callers have already tried that route. ! 86: */ ! 87: ! 88: void thread_swapin(thread) ! 89: thread_t thread; ! 90: { ! 91: switch (thread->state & TH_SWAP_STATE) { ! 92: case TH_SWAPPED: ! 93: /* ! 94: * Swapped out - queue for swapin thread. ! 95: */ ! 96: thread->state = (thread->state & ~TH_SWAP_STATE) ! 97: | TH_SW_COMING_IN; ! 98: swapper_lock(); ! 99: enqueue_tail(&swapin_queue, (queue_entry_t) thread); ! 100: swapper_unlock(); ! 101: thread_wakeup((event_t) &swapin_queue); ! 102: break; ! 103: ! 104: case TH_SW_COMING_IN: ! 105: /* ! 106: * Already queued for swapin thread, or being ! 107: * swapped in. ! 108: */ ! 109: break; ! 110: ! 111: default: ! 112: /* ! 113: * Already swapped in. ! 114: */ ! 115: panic("thread_swapin"); ! 116: } ! 117: } ! 118: ! 119: /* ! 120: * thread_doswapin: ! 121: * ! 122: * Swapin the specified thread, if it should be runnable, then put ! 123: * it on a run queue. No locks should be held on entry, as it is ! 124: * likely that this routine will sleep (waiting for stack allocation). ! 125: */ ! 126: void thread_doswapin(thread) ! 127: register thread_t thread; ! 128: { ! 129: spl_t s; ! 130: ! 131: /* ! 132: * Allocate the kernel stack. ! 133: */ ! 134: ! 135: stack_alloc(thread, thread_continue); ! 136: ! 137: /* ! 138: * Place on run queue. ! 139: */ ! 140: ! 141: s = splsched(); ! 142: thread_lock(thread); ! 143: thread->state &= ~(TH_SWAPPED | TH_SW_COMING_IN); ! 144: if (thread->state & TH_RUN) ! 145: thread_setrun(thread, TRUE); ! 146: thread_unlock(thread); ! 147: (void) splx(s); ! 148: } ! 149: ! 150: /* ! 151: * swapin_thread: [exported] ! 152: * ! 153: * This procedure executes as a kernel thread. Threads that need to ! 154: * be swapped in are swapped in by this thread. ! 155: */ ! 156: void swapin_thread_continue() ! 157: { ! 158: for (;;) { ! 159: register thread_t thread; ! 160: spl_t s; ! 161: ! 162: s = splsched(); ! 163: swapper_lock(); ! 164: ! 165: while ((thread = (thread_t) dequeue_head(&swapin_queue)) ! 166: != THREAD_NULL) { ! 167: swapper_unlock(); ! 168: (void) splx(s); ! 169: ! 170: thread_doswapin(thread); /* may block */ ! 171: ! 172: s = splsched(); ! 173: swapper_lock(); ! 174: } ! 175: ! 176: assert_wait((event_t) &swapin_queue, FALSE); ! 177: swapper_unlock(); ! 178: (void) splx(s); ! 179: counter(c_swapin_thread_block++); ! 180: thread_block(swapin_thread_continue); ! 181: } ! 182: } ! 183: ! 184: void swapin_thread() ! 185: { ! 186: stack_privilege(current_thread()); ! 187: ! 188: swapin_thread_continue(); ! 189: /*NOTREACHED*/ ! 190: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.