*
* @APPLE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
*/
/*
*/
-/*
- *
- * File: kern/thread_swap.c
- * Author: Avadis Tevanian, Jr.
- * Date: 1987
- *
- * Mach thread swapper:
- * 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 <kern/thread.h>
#include <kern/lock.h>
#include <vm/vm_kern.h>
#include <mach/vm_param.h>
#include <kern/sched_prim.h>
-#include <kern/sf.h>
#include <kern/processor.h>
#include <kern/thread_swap.h>
#include <kern/spl.h> /* for splsched */
#include <mach/policy.h>
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)
+decl_simple_lock_data(,swapin_lock)
mach_counter_t c_swapin_thread_block;
+void swapin_thread(void);
+
/*
- * swapper_init: [exported]
+ * swapin_init: [exported]
*
* Initialize the swapper module.
*/
-void swapper_init()
+void
+swapin_init(void)
{
queue_init(&swapin_queue);
- simple_lock_init(&swapper_lock_data, ETAP_THREAD_SWAPPER);
+ simple_lock_init(&swapin_lock, ETAP_THREAD_SWAPPER);
+ kernel_thread_with_priority(
+ kernel_task, BASEPRI_PREEMPT - 2,
+ swapin_thread, TRUE, TRUE);
}
/*
* 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.
+ * Place the specified thread in the list of threads to swapin.
+ * Called with thread locked, returned unlocked.
*/
-void thread_swapin(thread)
- thread_t thread;
+void
+thread_swapin(
+ register thread_t thread)
{
switch (thread->state & TH_STACK_STATE) {
+
case TH_STACK_HANDOFF:
/*
- * Swapped out - queue for swapin thread.
+ * Swapped out.
*/
- thread->state = (thread->state & ~TH_STACK_STATE)
- | TH_STACK_COMING_IN;
- swapper_lock();
+ thread->state = (thread->state & ~TH_STACK_STATE) | TH_STACK_ALLOC;
+ thread_unlock(thread);
+ simple_lock(&swapin_lock);
enqueue_tail(&swapin_queue, (queue_entry_t) thread);
- swapper_unlock();
- thread_wakeup((event_t) &swapin_queue);
+ simple_unlock(&swapin_lock);
+ thread_wakeup((event_t)&swapin_queue);
break;
- case TH_STACK_COMING_IN:
+ case TH_STACK_ALLOC:
/*
- * Already queued for swapin thread, or being
- * swapped in.
+ * Already queued.
*/
+ thread_unlock(thread);
break;
- default:
+ default:
/*
* Already swapped in.
*/
* 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).
+ * it on a run queue.
*/
-void thread_doswapin(thread)
- register thread_t thread;
+void
+thread_doswapin(
+ register thread_t thread)
{
- spl_t s;
- vm_offset_t stack;
-
- /*
- * do machdep allocation
- */
+ vm_offset_t stack;
+ spl_t s;
/*
* Allocate the kernel stack.
/*
* Place on run queue.
*/
-
s = splsched();
thread_lock(thread);
- thread->state &= ~(TH_STACK_HANDOFF | TH_STACK_COMING_IN);
+ thread->state &= ~(TH_STACK_HANDOFF | TH_STACK_ALLOC);
if (thread->state & TH_RUN)
- thread_setrun(thread, TRUE, FALSE);
+ thread_setrun(thread, HEAD_Q);
thread_unlock(thread);
(void) splx(s);
}
* This procedure executes as a kernel thread. Threads that need to
* be swapped in are swapped in by this thread.
*/
-void swapin_thread_continue()
+void
+swapin_thread_continue(void)
{
- for (;;) {
- register thread_t thread;
- spl_t s;
-
- s = splsched();
- swapper_lock();
-
- while ((thread = (thread_t) dequeue_head(&swapin_queue))
- != THREAD_NULL) {
- swapper_unlock();
- (void) splx(s);
-
- thread_doswapin(thread); /* may block */
-
- s = splsched();
- swapper_lock();
- }
-
- assert_wait((event_t) &swapin_queue, THREAD_UNINT);
- swapper_unlock();
- (void) splx(s);
- counter(c_swapin_thread_block++);
-#if defined (__i386__)
- thread_block((void (*)(void)) 0);
-#else
- thread_block(swapin_thread_continue);
-#endif
+ register thread_t thread;
+
+ (void)splsched();
+ simple_lock(&swapin_lock);
+
+ while ((thread = (thread_t)dequeue_head(&swapin_queue)) != THREAD_NULL) {
+ simple_unlock(&swapin_lock);
+ (void)spllo();
+
+ thread_doswapin(thread);
+
+ (void)splsched();
+ simple_lock(&swapin_lock);
}
+
+ assert_wait((event_t)&swapin_queue, THREAD_UNINT);
+ simple_unlock(&swapin_lock);
+ (void)spllo();
+
+ counter(c_swapin_thread_block++);
+ thread_block(swapin_thread_continue);
+ /*NOTREACHED*/
}
-void swapin_thread()
+void
+swapin_thread(void)
{
- stack_privilege(current_thread());
- current_thread()->vm_privilege = TRUE;
+ thread_t self = current_thread();
+
+ stack_privilege(self);
swapin_thread_continue();
/*NOTREACHED*/