|
|
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>
1.1.1.2 root 49: #include <kern/debug.h>
1.1 root 50: #include <kern/thread.h>
51: #include <kern/lock.h>
52: #include <vm/vm_map.h>
53: #include <vm/vm_kern.h>
54: #include <mach/vm_param.h>
55: #include <kern/sched_prim.h>
56: #include <kern/processor.h>
57: #include <kern/thread_swap.h>
58: #include <machine/machspl.h> /* for splsched */
59:
60:
61:
62: queue_head_t swapin_queue;
63: decl_simple_lock_data(, swapper_lock_data)
64:
65: #define swapper_lock() simple_lock(&swapper_lock_data)
66: #define swapper_unlock() simple_unlock(&swapper_lock_data)
67:
68: /*
69: * swapper_init: [exported]
70: *
71: * Initialize the swapper module.
72: */
1.1.1.2 root 73: void swapper_init(void)
1.1 root 74: {
75: queue_init(&swapin_queue);
76: simple_lock_init(&swapper_lock_data);
77: }
78:
79: /*
80: * thread_swapin: [exported]
81: *
82: * Place the specified thread in the list of threads to swapin. It
83: * is assumed that the thread is locked, therefore we are at splsched.
84: *
85: * We don't bother with stack_alloc_try to optimize swapin;
86: * our callers have already tried that route.
87: */
88:
1.1.1.3 root 89: void thread_swapin(thread_t thread)
1.1 root 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();
1.1.1.3 root 99: enqueue_tail(&swapin_queue, &(thread->links));
1.1 root 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: */
1.1.1.4 ! root 126: kern_return_t thread_doswapin(thread_t thread)
1.1 root 127: {
1.1.1.4 ! root 128: kern_return_t kr;
1.1 root 129: spl_t s;
130:
131: /*
132: * Allocate the kernel stack.
133: */
134:
1.1.1.4 ! root 135: kr = stack_alloc(thread, thread_continue);
! 136: if (kr != KERN_SUCCESS)
! 137: return kr;
1.1 root 138:
139: /*
140: * Place on run queue.
141: */
142:
143: s = splsched();
144: thread_lock(thread);
145: thread->state &= ~(TH_SWAPPED | TH_SW_COMING_IN);
146: if (thread->state & TH_RUN)
147: thread_setrun(thread, TRUE);
148: thread_unlock(thread);
149: (void) splx(s);
1.1.1.4 ! root 150: return KERN_SUCCESS;
1.1 root 151: }
152:
153: /*
154: * swapin_thread: [exported]
155: *
156: * This procedure executes as a kernel thread. Threads that need to
157: * be swapped in are swapped in by this thread.
158: */
1.1.1.3 root 159: void __attribute__((noreturn)) swapin_thread_continue(void)
1.1 root 160: {
161: for (;;) {
1.1.1.3 root 162: thread_t thread;
1.1 root 163: spl_t s;
164:
165: s = splsched();
166: swapper_lock();
167:
168: while ((thread = (thread_t) dequeue_head(&swapin_queue))
169: != THREAD_NULL) {
1.1.1.4 ! root 170: kern_return_t kr;
1.1 root 171: swapper_unlock();
172: (void) splx(s);
173:
1.1.1.4 ! root 174: kr = thread_doswapin(thread); /* may block */
1.1 root 175:
176: s = splsched();
177: swapper_lock();
1.1.1.4 ! root 178:
! 179: if (kr != KERN_SUCCESS) {
! 180: enqueue_head(&swapin_queue,
! 181: (queue_entry_t) thread);
! 182: break;
! 183: }
1.1 root 184: }
185:
186: assert_wait((event_t) &swapin_queue, FALSE);
187: swapper_unlock();
188: (void) splx(s);
189: counter(c_swapin_thread_block++);
190: thread_block(swapin_thread_continue);
191: }
192: }
193:
1.1.1.2 root 194: void swapin_thread(void)
1.1 root 195: {
196: stack_privilege(current_thread());
197:
198: swapin_thread_continue();
199: /*NOTREACHED*/
200: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.