]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/thread_swap.c
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / kern / thread_swap.c
index 46bb6cc9eb57129b29bf025e543a1d7719daba50..60655208a189531d97a285c1d1cc2f3ce1d7cbd7 100644 (file)
@@ -3,19 +3,22 @@
  *
  * @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>
@@ -73,7 +59,6 @@
 #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.
                 */
@@ -145,18 +132,14 @@ void thread_swapin(thread)
  *     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.
@@ -167,12 +150,11 @@ void thread_doswapin(thread)
        /*
         *      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);
 }
@@ -183,42 +165,39 @@ void thread_doswapin(thread)
  *     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*/