1 /*
2 * Mach Operating System
3 * Copyright (c) 1993-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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: thread_swap.c,v $
29 * Revision 2.13 93/11/17 17:31:37 dbg
30 * Break up thread lock.
31 * [93/05/26 dbg]
32 *
33 * Added AST_KERNEL_CHECK to swapper thread. Added ANSI
34 * function prototypes. Declare non-returning functions
35 * as returning 'no_return'.
36 * [93/05/04 dbg]
37 *
38 * Revision 2.12 93/05/15 18:56:04 mrt
39 * machparam.h -> machspl.h
40 *
41 * Revision 2.11 93/01/14 17:37:17 danner
42 * Corrected casts for thread_wakeup and assert_wait.
43 * [93/01/12 danner]
44 * 64bit cleanup. Proper spl typing.
45 * [92/12/01 af]
46 *
47 * Revision 2.10 92/08/03 17:40:14 jfriedl
48 * removed silly prototypes
49 * [92/08/02 jfriedl]
50 *
51 * Revision 2.9 92/05/21 17:16:48 jfriedl
52 * tried prototypes.
53 * [92/05/20 jfriedl]
54 *
55 * Revision 2.8 91/07/31 17:50:04 dbg
56 * Revise scheduling state machine.
57 * [91/07/30 17:07:03 dbg]
58 *
59 * Revision 2.7 91/05/14 16:49:08 mrt
60 * Correcting copyright
61 *
62 * Revision 2.6 91/03/16 14:53:09 rpd
63 * Removed thread_swapout.
64 * [91/02/24 rpd]
65 * Added swapin_thread_continue.
66 * Simplified the state machine. Now it uses only
67 * TH_SW_IN, TH_SW_OUT, TH_SW_COMING_IN.
68 * [91/01/20 rpd]
69 *
70 * Simplified thread_swapin.
71 * [91/01/17 rpd]
72 *
73 * Revision 2.5 91/02/05 17:30:40 mrt
74 * Changed to new Mach copyright
75 * [91/02/01 16:20:14 mrt]
76 *
77 * Revision 2.4 91/01/08 15:18:20 rpd
78 * Added continuation argument to thread_block.
79 * [90/12/08 rpd]
80 *
81 * Removed swapout_thread, swapout_threads,
82 * swapout_scan, thread_swapout.
83 * [90/11/11 rpd]
84 *
85 * Revision 2.3 90/06/02 14:57:18 rpd
86 * In thread_swapout, free the thread's cached message buffer.
87 * [90/04/23 rpd]
88 * Converted to new processor set technology.
89 * [90/03/26 22:26:32 rpd]
90 *
91 * Revision 2.2 89/12/08 19:52:35 rwd
92 * Added call to zone_gc()
93 * [89/11/21 rwd]
94 *
95 * Revision 2.1 89/08/03 15:48:24 rwd
96 * Created.
97 *
98 * Revision 2.4 88/10/27 10:50:40 rpd
99 * Changed includes to the new style. Removed extraneous semis
100 * from the swapper_lock/swapper_unlock macros.
101 * [88/10/26 14:49:09 rpd]
102 *
103 * 15-Jun-88 Michael Young (mwyoung) at Carnegie-Mellon University
104 * Fix improper handling of swapper_lock() in swapin_thread().
105 * Problem discovery and elegant recoding due to Richard Draves.
106 *
107 * 4-May-88 David Golub (dbg) at Carnegie-Mellon University
108 * Remove vax-specific code.
109 *
110 * 1-Mar-88 David Black (dlb) at Carnegie-Mellon University
111 * Logic change due to replacement of wait_time field in thread
112 * with sched_stamp. Extra argument to thread_setrun().
113 *
114 * 25-Jan-88 Richard Sanzi (sanzi) at Carnegie-Mellon University
115 * Notify pcb module that pcb is about to be unwired by calling
116 * pcb_synch(thread).
117 *
118 * 21-Jan-88 David Golub (dbg) at Carnegie-Mellon University
119 * Fix lots more race conditions (thread_swapin called during
120 * swapout, thread_swapin called twice) by adding a swapper state
121 * machine to each thread. Moved thread_swappable here from
122 * kern/thread.c.
123 *
124 * 12-Nov-87 David Golub (dbg) at Carnegie-Mellon University
125 * Fix race condition in thread_swapout: mark thread as swapped
126 * before swapping out its stack, so that an intervening wakeup
127 * will put it on the swapin list.
128 *
129 * 5-Oct-87 David Golub (dbg) at Carnegie-Mellon University
130 * Changed to new scheduling state machine.
131 *
132 * 15-Sep-87 Michael Young (mwyoung) at Carnegie-Mellon University
133 * De-linted.
134 *
135 * 5-Sep-87 Michael Young (mwyoung) at Carnegie-Mellon University
136 * Added check for THREAD_SWAPPABLE in swapout_scan().
137 *
138 * 14-Jul-87 David Golub (dbg) at Carnegie-Mellon University
139 * Truncate the starting address and round up the size given to
140 * vm_map_pageable, when wiring/unwiring kernel stacks.
141 * KERNEL_STACK_SIZE is not necessarily a multiple of page_size; if
142 * it isn't, forgetting to round the address and size to page
143 * boundaries results in panic. Kmem_alloc and kmem_free, used in
144 * thread.c to allocate and free kernel stacks, already round to
145 * page boundaries.
146 *
147 * 26-Jun-87 Michael Young (mwyoung) at Carnegie-Mellon University
148 * Add thread_swapout_allowed flag to make it easy to turn
149 * off swapping when debugging.
150 *
151 * 4-Jun-87 David Golub (dbg) at Carnegie-Mellon University
152 * Pass correct number of parameters to lock_init - initialize
153 * swap_lock as sleepable instead of calling lock_sleepable
154 * separately.
155 *
156 * 1-Apr-87 Avadis Tevanian (avie) at Carnegie-Mellon University
157 * Include vm_param.h to pick up KERNEL_STACK_SIZE definition.
158 *
159 * 20-Mar-87 Avadis Tevanian (avie) at Carnegie-Mellon University
160 * Lower ipl before calling thread_swapout().
161 *
162 * 19-Mar-87 David Golub (dbg) at Carnegie-Mellon University
163 * Fix one race condition in this (not so buggy) version - since
164 * thread_swapin can be called from interrupts, must raise IPL when
165 * locking swapper_lock.
166 *
167 * 09-Mar-87 Avadis Tevanian (avie) at Carnegie-Mellon University
168 * Created, based somewhat loosely on the earlier (which was a highly
169 * buggy, race condition filled version).
170 *
171 */
172 /*
173 *
174 * File: kern/thread_swap.c
175 * Author: Avadis Tevanian, Jr.
176 * Date: 1987
177 *
178 * Mach thread swapper:
179 * Find idle threads to swap, freeing up kernel stack resources
180 * at the expense of allowing them to execute.
181 *
182 * Swap in threads that need to be run. This is done here
183 * by the swapper thread since it cannot be done (in general)
184 * when the kernel tries to place a thread on a run queue.
185 *
186 * Note: The act of swapping a thread in Mach does not mean that
187 * its memory gets forcibly swapped to secondary storage. The memory
188 * for the task corresponding to a swapped thread is paged out
189 * through the normal paging mechanism.
190 *
191 */
192
193 #include <ipc/ipc_kmsg.h>
194 #include <kern/counters.h>
195 #include <kern/thread.h>
196 #include <kern/lock.h>
197 #include <vm/vm_map.h>
198 #include <vm/vm_kern.h>
199 #include <mach/vm_param.h>
200 #include <kern/sched_prim.h>
201 #include <kern/stack.h>
202 #include <kern/processor.h>
203 #include <kern/thread_swap.h>
204 #include <machine/machspl.h> /* for splsched */
205
206
207
208 queue_head_t swapin_queue;
209 decl_simple_lock_data(, swapper_lock_data)
210
211 #define swapper_lock() simple_lock(&swapper_lock_data)
212 #define swapper_unlock() simple_unlock(&swapper_lock_data)
213
214 /*
215 * swapper_init: [exported]
216 *
217 * Initialize the swapper module.
218 */
219 void swapper_init(void)
220 {
221 queue_init(&swapin_queue);
222 simple_lock_init(&swapper_lock_data);
223 }
224
225 /*
226 * thread_swapin: [exported]
227 *
228 * Place the specified thread in the list of threads to swapin. It
229 * is assumed that the thread is locked, therefore we are at splsched.
230 *
231 * We don't bother with stack_alloc_try to optimize swapin;
232 * our callers have already tried that route.
233 */
234
235 void thread_swapin(
236 thread_t thread)
237 {
238 switch (thread->state & TH_SWAP_STATE) {
239 case TH_SWAPPED:
240 /*
241 * Swapped out - queue for swapin thread.
242 */
243 thread->state = (thread->state & ~TH_SWAP_STATE)
244 | TH_SW_COMING_IN;
245 swapper_lock();
246 enqueue_tail(&swapin_queue, (queue_entry_t) thread);
247 swapper_unlock();
248 thread_wakeup((event_t) &swapin_queue);
249 break;
250
251 case TH_SW_COMING_IN:
252 /*
253 * Already queued for swapin thread, or being
254 * swapped in.
255 */
256 break;
257
258 default:
259 /*
260 * Already swapped in.
261 */
262 panic("thread_swapin");
263 }
264 }
265
266 /*
267 * thread_doswapin:
268 *
269 * Swapin the specified thread. If it should be runnable, then put
270 * it on a run queue. No locks should be held on entry, as it is
271 * likely that this routine will sleep (waiting for stack allocation).
272 */
273 void thread_doswapin(
274 register thread_t thread)
275 {
276 spl_t s;
277
278 /*
279 * Allocate the kernel stack.
280 */
281
282 stack_alloc(thread, thread_continue);
283
284 /*
285 * Place on run queue.
286 */
287
288 s = splsched();
289 thread_sched_lock(thread);
290 thread->state &= ~(TH_SWAPPED | TH_SW_COMING_IN);
291 if (thread->state & TH_RUN)
292 thread_setrun(thread, TRUE);
293 thread_sched_unlock(thread);
294 splx(s);
295 }
296
297 /*
298 * swapin_thread: [exported]
299 *
300 * This procedure executes as a kernel thread. Threads that need to
301 * be swapped in are swapped in by this thread.
302 */
303 no_return swapin_thread_continue(void)
304 {
305 for (;;) {
306 register thread_t thread;
307 spl_t s;
308
309 s = splsched();
310 swapper_lock();
311
312 while ((thread = (thread_t) dequeue_head(&swapin_queue))
313 != THREAD_NULL) {
314 swapper_unlock();
315 splx(s);
316
317 thread_doswapin(thread); /* may block */
318
319 AST_KERNEL_CHECK(cpu_number());
320
321 s = splsched();
322 swapper_lock();
323 }
324
325 assert_wait((event_t) &swapin_queue, FALSE);
326 swapper_unlock();
327 splx(s);
328 counter(c_swapin_thread_block++);
329 thread_block(swapin_thread_continue);
330 }
331 }
332
333 no_return swapin_thread(void)
334 {
335 stack_privilege(current_thread());
336
337 swapin_thread_continue();
338 /*NOTREACHED*/
339 }
Cache object: 46f4fe086a11ab163500f2feb8e35ff5
|