123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * 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 ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS 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: kern/thread_swap.c
- * Author: Avadis Tevanian, Jr.
- * Date: 1987
- *
- * Mach thread swapper:
- * Find idle threads to swap, freeing up kernel stack resources
- * at the expense of allowing them to execute.
- *
- * Swap in threads that need to be run. This is done here
- * by the swapper thread since it cannot be done (in general)
- * when the kernel tries to place a thread on a run queue.
- *
- * Note: The act of swapping a thread in Mach does not mean that
- * its memory gets forcibly swapped to secondary storage. The memory
- * for the task corresponding to a swapped thread is paged out
- * through the normal paging mechanism.
- *
- */
- #include <ipc/ipc_kmsg.h>
- #include <kern/counters.h>
- #include <kern/debug.h>
- #include <kern/thread.h>
- #include <kern/lock.h>
- #include <vm/vm_map.h>
- #include <vm/vm_kern.h>
- #include <mach/vm_param.h>
- #include <kern/sched_prim.h>
- #include <kern/processor.h>
- #include <kern/thread_swap.h>
- #include <machine/machspl.h> /* for splsched */
- queue_head_t swapin_queue;
- decl_simple_lock_data(, swapper_lock_data)
- #define swapper_lock() simple_lock(&swapper_lock_data)
- #define swapper_unlock() simple_unlock(&swapper_lock_data)
- /*
- * swapper_init: [exported]
- *
- * Initialize the swapper module.
- */
- void swapper_init(void)
- {
- queue_init(&swapin_queue);
- simple_lock_init(&swapper_lock_data);
- }
- /*
- * thread_swapin: [exported]
- *
- * Place the specified thread in the list of threads to swapin. It
- * is assumed that the thread is locked, therefore we are at splsched.
- *
- * We don't bother with stack_alloc_try to optimize swapin;
- * our callers have already tried that route.
- */
- void thread_swapin(thread_t thread)
- {
- switch (thread->state & TH_SWAP_STATE) {
- case TH_SWAPPED:
- /*
- * Swapped out - queue for swapin thread.
- */
- thread->state = (thread->state & ~TH_SWAP_STATE)
- | TH_SW_COMING_IN;
- swapper_lock();
- enqueue_tail(&swapin_queue, &(thread->links));
- swapper_unlock();
- thread_wakeup((event_t) &swapin_queue);
- break;
- case TH_SW_COMING_IN:
- /*
- * Already queued for swapin thread, or being
- * swapped in.
- */
- break;
- default:
- /*
- * Already swapped in.
- */
- panic("thread_swapin");
- }
- }
- /*
- * thread_doswapin:
- *
- * Swapin the specified thread, if it should be runnable, then put
- * it on a run queue. No locks should be held on entry, as it is
- * likely that this routine will sleep (waiting for stack allocation).
- */
- kern_return_t thread_doswapin(thread_t thread)
- {
- kern_return_t kr;
- spl_t s;
- /*
- * Allocate the kernel stack.
- */
- kr = stack_alloc(thread, thread_continue);
- if (kr != KERN_SUCCESS)
- return kr;
- /*
- * Place on run queue.
- */
- s = splsched();
- thread_lock(thread);
- thread->state &= ~(TH_SWAPPED | TH_SW_COMING_IN);
- if (thread->state & TH_RUN)
- thread_setrun(thread, TRUE);
- thread_unlock(thread);
- (void) splx(s);
- return KERN_SUCCESS;
- }
- /*
- * swapin_thread: [exported]
- *
- * This procedure executes as a kernel thread. Threads that need to
- * be swapped in are swapped in by this thread.
- */
- void __attribute__((noreturn)) swapin_thread_continue(void)
- {
- for (;;) {
- thread_t thread;
- spl_t s;
- s = splsched();
- swapper_lock();
- while ((thread = (thread_t) dequeue_head(&swapin_queue))
- != THREAD_NULL) {
- kern_return_t kr;
- swapper_unlock();
- (void) splx(s);
- kr = thread_doswapin(thread); /* may block */
- s = splsched();
- swapper_lock();
- if (kr != KERN_SUCCESS) {
- enqueue_head(&swapin_queue,
- (queue_entry_t) thread);
- break;
- }
- }
- assert_wait((event_t) &swapin_queue, FALSE);
- swapper_unlock();
- (void) splx(s);
- counter(c_swapin_thread_block++);
- thread_block(swapin_thread_continue);
- }
- }
- void swapin_thread(void)
- {
- stack_privilege(current_thread());
- swapin_thread_continue();
- /*NOTREACHED*/
- }
|