]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/thread_act.c
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / kern / thread_act.c
index 4320b05dda759156e90e364b3ac57ac2d9197992..129f39d9a1f3ab5c484ef4d4881927a1f5e1b16c 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@
  */
@@ -56,7 +59,6 @@
 #include <kern/task.h>
 #include <kern/task_swap.h>
 #include <kern/thread_act.h>
-#include <kern/thread_pool.h>
 #include <kern/sched_prim.h>
 #include <kern/misc_protos.h>
 #include <kern/assert.h>
@@ -85,26 +87,30 @@ unsigned int        watchacts =       0 /* WA_ALL */
  * Track the number of times we need to swapin a thread to deallocate it.
  */
 int act_free_swapin = 0;
+boolean_t first_act;
 
 /*
  * Forward declarations for functions local to this file.
  */
-kern_return_t  act_abort( thread_act_t, int);
+kern_return_t  act_abort( thread_act_t, boolean_t);
 void           special_handler(ReturnHandler *, thread_act_t);
-void           nudge(thread_act_t);
 kern_return_t  act_set_state_locked(thread_act_t, int,
                                        thread_state_t,
                                        mach_msg_type_number_t);
 kern_return_t  act_get_state_locked(thread_act_t, int,
                                        thread_state_t,
                                        mach_msg_type_number_t *);
+void           act_set_astbsd(thread_act_t);
 void           act_set_apc(thread_act_t);
-void           act_clr_apc(thread_act_t);
 void           act_user_to_kernel(thread_act_t);
 void           act_ulock_release_all(thread_act_t thr_act);
 
 void           install_special_handler_locked(thread_act_t);
 
+static void            act_disable(thread_act_t);
+
+struct thread_activation       pageout_act;
+
 static zone_t  thr_act_zone;
 
 /*
@@ -114,79 +120,65 @@ static zone_t     thr_act_zone;
 
 /*
  * Internal routine to terminate a thread.
- * Called with task locked.
+ * Sometimes called with task already locked.
  */
 kern_return_t
 thread_terminate_internal(
-       register thread_act_t   thr_act)
+       register thread_act_t   act)
 {
-       thread_t        thread;
-       task_t          task;
-       struct ipc_port *iplock;
-       kern_return_t   ret;
+       kern_return_t   result;
+       thread_t                thread;
 
-#if    THREAD_SWAPPER
-       thread_swap_disable(thr_act);
-#endif /* THREAD_SWAPPER */
+       thread = act_lock_thread(act);
 
-       thread = act_lock_thread(thr_act);
-       if (!thr_act->active) {
-               act_unlock_thread(thr_act);
-               return(KERN_TERMINATED);
+       if (!act->active) {
+               act_unlock_thread(act);
+               return (KERN_TERMINATED);
        }
 
-       act_disable_task_locked(thr_act);
-       ret = act_abort(thr_act,FALSE);
+       act_disable(act);
+       result = act_abort(act, FALSE);
 
-#if    NCPUS > 1
        /* 
         * Make sure this thread enters the kernel
+        * Must unlock the act, but leave the shuttle
+        * captured in this act.
         */
        if (thread != current_thread()) {
-               thread_hold(thr_act);
-               act_unlock_thread(thr_act);
+               act_unlock(act);
 
-               if (thread_stop_wait(thread))
+               if (thread_stop(thread))
                        thread_unstop(thread);
                else
-                       ret = KERN_ABORTED;
+                       result = KERN_ABORTED;
 
-               (void)act_lock_thread(thr_act);
-               thread_release(thr_act);
+               act_lock(act);
        }
-#endif /* NCPUS > 1 */
 
-       act_unlock_thread(thr_act);
-       return(ret);
+       clear_wait(thread, act->inited? THREAD_INTERRUPTED: THREAD_AWAKENED);
+       act_unlock_thread(act);
+
+       return (result);
 }
 
 /*
- * Terminate a thread.  Called with nothing locked.
- * Returns same way.
+ * Terminate a thread.
  */
 kern_return_t
 thread_terminate(
-       register thread_act_t   thr_act)
+       register thread_act_t   act)
 {
-       task_t          task;
-       kern_return_t   ret;
+       kern_return_t   result;
 
-       if (thr_act == THR_ACT_NULL)
-               return KERN_INVALID_ARGUMENT;
+       if (act == THR_ACT_NULL)
+               return (KERN_INVALID_ARGUMENT);
 
-       task = thr_act->task;
-       if (((task == kernel_task) || (thr_act->kernel_loaded == TRUE))
-           && (current_act() != thr_act)) {
-               return(KERN_FAILURE);
-        }
+       if (    (act->task == kernel_task       ||
+                        act->kernel_loaded                     )       &&
+                       act != current_act()                    )
+               return (KERN_FAILURE);
 
-       /*
-        * Take the task lock and then call the internal routine
-        * that terminates a thread (it needs the task locked).
-        */
-       task_lock(task);
-       ret = thread_terminate_internal(thr_act);
-       task_unlock(task);
+       result = thread_terminate_internal(act);
 
        /*
         * If a kernel thread is terminating itself, force an AST here.
@@ -194,33 +186,35 @@ thread_terminate(
         * code - and all threads finish their own termination in the
         * special handler APC.
         */
-       if (    (       thr_act->task == kernel_task    ||
-                               thr_act->kernel_loaded == TRUE  )       && 
-                       current_act() == thr_act                                        ) {
+       if (    act->task == kernel_task        ||
+                        act->kernel_loaded                     ) {
+               assert(act == current_act());
                ast_taken(AST_APC, FALSE);
-               panic("thread_terminate(): returning from ast_taken() for %x kernel activation\n", thr_act);
-        }
+               panic("thread_terminate");
+       }
 
-       return ret;
+       return (result);
 }
 
 /*
- *     thread_hold:
+ * Suspend execution of the specified thread.
+ * This is a recursive-style suspension of the thread, a count of
+ * suspends is maintained.
  *
- *     Suspend execution of the specified thread.
- *     This is a recursive-style suspension of the thread, a count of
- *     suspends is maintained.
- *
- *     Called with thr_act locked "appropriately" for synchrony with
- *     RPC (see act_lock_thread()).  Returns same way.
+ * Called with act_lock held.
  */
 void
 thread_hold(
-       register thread_act_t   thr_act)
+       register thread_act_t   act)
 {
-       if (thr_act->suspend_count++ == 0) {
-               install_special_handler(thr_act);
-               nudge(thr_act);
+       thread_t        thread = act->thread;
+
+       if (act->suspend_count++ == 0) {
+               install_special_handler(act);
+               if (    act->inited                                     &&
+                               thread != THREAD_NULL           &&
+                               thread->top_act == act          )
+                       thread_wakeup_one(&act->suspend_count);
        }
 }
 
@@ -228,84 +222,99 @@ thread_hold(
  * Decrement internal suspension count for thr_act, setting thread
  * runnable when count falls to zero.
  *
- * Called with thr_act locked "appropriately" for synchrony
- * with RPC (see act_lock_thread()).
+ * Called with act_lock held.
  */
 void
 thread_release(
-       register thread_act_t   thr_act)
+       register thread_act_t   act)
 {
-       if( thr_act->suspend_count &&
-               (--thr_act->suspend_count == 0) )
-               nudge( thr_act );
+       thread_t        thread = act->thread;
+
+       if (    act->suspend_count > 0          &&
+                       --act->suspend_count == 0       &&
+                       thread != THREAD_NULL           &&
+                       thread->top_act == act          ) {
+               if (!act->inited) {
+                       clear_wait(thread, THREAD_AWAKENED);
+                       act->inited = TRUE;
+               }
+               else
+                       thread_wakeup_one(&act->suspend_count);
+       }
 }
 
 kern_return_t
 thread_suspend(
-       register thread_act_t   thr_act)
+       register thread_act_t   act)
 {
-       thread_t                thread;
+       thread_t        thread;
 
-       if (thr_act == THR_ACT_NULL) {
-               return(KERN_INVALID_ARGUMENT);
-       }
-       thread = act_lock_thread(thr_act);
-       if (!thr_act->active) {
-               act_unlock_thread(thr_act);
-               return(KERN_TERMINATED);
+       if (act == THR_ACT_NULL)
+               return (KERN_INVALID_ARGUMENT);
+
+       thread = act_lock_thread(act);
+
+       if (!act->active) {
+               act_unlock_thread(act);
+               return (KERN_TERMINATED);
        }
-       if (thr_act->user_stop_count++ == 0 &&
-               thr_act->suspend_count++ == 0 ) {
-               install_special_handler(thr_act);
-               if (thread &&
-                       thr_act == thread->top_act && thread != current_thread()) {
-                       nudge(thr_act);
-                       act_unlock_thread(thr_act);
-                       (void)thread_wait(thread);
-               }
-               else {
-                       /*
-                        * No need to wait for target thread
-                        */
-                       act_unlock_thread(thr_act);
+
+       if (    act->user_stop_count++ == 0             &&
+                       act->suspend_count++ == 0               ) {
+               install_special_handler(act);
+               if (    thread != current_thread()              &&
+                               thread != THREAD_NULL                   &&
+                               thread->top_act == act                  ) {
+                       assert(act->inited);
+                       thread_wakeup_one(&act->suspend_count);
+                       act_unlock_thread(act);
+
+                       thread_wait(thread);
                }
+               else
+                       act_unlock_thread(act);
        }
-       else {
-               /*
-                * Thread is already suspended
-                */
-               act_unlock_thread(thr_act);
-       }
-       return(KERN_SUCCESS);
+       else
+               act_unlock_thread(act);
+
+       return (KERN_SUCCESS);
 }
 
 kern_return_t
 thread_resume(
-       register thread_act_t   thr_act)
+       register thread_act_t   act)
 {
-       register kern_return_t  ret;
-       spl_t                   s;
+       kern_return_t   result = KERN_SUCCESS;
        thread_t                thread;
 
-       if (thr_act == THR_ACT_NULL)
-               return(KERN_INVALID_ARGUMENT);
-       thread = act_lock_thread(thr_act);
-       ret = KERN_SUCCESS;
+       if (act == THR_ACT_NULL)
+               return (KERN_INVALID_ARGUMENT);
 
-       if (thr_act->active) {
-               if (thr_act->user_stop_count > 0) {
-                       if( --thr_act->user_stop_count == 0 ) {
-                               --thr_act->suspend_count;
-                               nudge( thr_act );
+       thread = act_lock_thread(act);
+
+       if (act->active) {
+               if (act->user_stop_count > 0) {
+                       if (    --act->user_stop_count == 0             &&
+                                       --act->suspend_count == 0               &&
+                                       thread != THREAD_NULL                   &&
+                                       thread->top_act == act                  ) {
+                               if (!act->inited) {
+                                       clear_wait(thread, THREAD_AWAKENED);
+                                       act->inited = TRUE;
+                               }
+                               else
+                                       thread_wakeup_one(&act->suspend_count);
                        }
                }
                else
-                       ret = KERN_FAILURE;
+                       result = KERN_FAILURE;
        }
        else
-               ret = KERN_TERMINATED;
-       act_unlock_thread( thr_act );
-       return ret;
+               result = KERN_TERMINATED;
+
+       act_unlock_thread(act);
+
+       return (result);
 }
 
 /* 
@@ -317,24 +326,10 @@ thread_resume(
  */
 kern_return_t
 post_alert( 
-       register thread_act_t   thr_act,
-       unsigned                alert_bits )
+       register thread_act_t   act,
+       unsigned                                alert_bits)
 {
-       thread_act_t    next;
-       thread_t        thread;
-
-       /* 
-        * Chase the chain, setting alert bits and installing
-        * special handlers for each thread act.
-        */
-       /*** Not yet SMP safe ***/
-       /*** Worse, where's the activation locking as the chain is walked? ***/
-       for (next = thr_act; next != THR_ACT_NULL; next = next->higher) {
-               next->alerts |= alert_bits;
-               install_special_handler_locked(next);
-       }
-
-       return(KERN_SUCCESS);
+       panic("post_alert");
 }
 
 /*
@@ -369,196 +364,91 @@ thread_depress_abort(
 
 
 /*
- * Already locked: all RPC-related locks for thr_act (see
- * act_lock_thread()).
+ * Indicate that the activation should run its
+ * special handler to detect the condition.
+ *
+ * Called with act_lock held.
  */
 kern_return_t
-act_abort( thread_act_t thr_act, int chain_break )
+act_abort(
+       thread_act_t    act, 
+       boolean_t       chain_break )
 {
-       spl_t                   spl;
-       thread_t                thread;
-       struct ipc_port         *iplock = thr_act->pool_port;
-       thread_act_t            orphan;
-       kern_return_t           kr;
-       etap_data_t             probe_data;
-
-       ETAP_DATA_LOAD(probe_data[0], thr_act);
-       ETAP_DATA_LOAD(probe_data[1], thr_act->thread);
-       ETAP_PROBE_DATA(ETAP_P_ACT_ABORT,
-                       0,
-                       current_thread(),
-                       &probe_data,
-                       ETAP_DATA_ENTRY*2);
+       thread_t        thread = act->thread;
+       spl_t           s = splsched();
 
-       /*
-        *  If the target thread activation is not the head... 
-        */
-       if ( thr_act->thread->top_act != thr_act ) {
-               /*
-                * mark the activation for abort,
-                * update the suspend count,
-                * always install the special handler
-                */
-               install_special_handler(thr_act);
-
-#ifdef AGRESSIVE_ABORT
-               /* release state buffer for target's outstanding invocation */
-               if (unwind_invoke_state(thr_act) != KERN_SUCCESS) {
-                       panic("unwind_invoke_state failure");
-               }
+       assert(thread->top_act == act);
 
-               /* release state buffer for target's incoming invocation */
-               if (thr_act->lower != THR_ACT_NULL) {
-                       if (unwind_invoke_state(thr_act->lower)
-                           != KERN_SUCCESS) {
-                               panic("unwind_invoke_state failure");
-                       }
-               }
-
-               /* unlink target thread activation from shuttle chain */
-               if ( thr_act->lower == THR_ACT_NULL ) {
-                       /*
-                        * This is the root thread activation of the chain.
-                        * Unlink the root thread act from the bottom of
-                        * the chain.
-                        */
-                       thr_act->higher->lower = THR_ACT_NULL;
-               } else {
-                       /*
-                        * This thread act is in the middle of the chain.
-                        * Unlink the thread act from the middle of the chain.
-                        */
-                       thr_act->higher->lower = thr_act->lower;
-                       thr_act->lower->higher = thr_act->higher;
-
-                       /* set the terminated bit for RPC return processing */
-                       thr_act->lower->alerts |= SERVER_TERMINATED;
-               }
-
-               orphan = thr_act->higher;
-
-               /* remove the activation from its thread pool */
-               /* (note: this is okay for "rooted threads," too) */
-               act_locked_act_set_thread_pool(thr_act, IP_NULL);
-
-               /* (just to be thorough) release the IP lock */
-               if (iplock != IP_NULL) ip_unlock(iplock);
-
-               /* release one more reference for a rooted thread */
-               if (iplock == IP_NULL) act_locked_act_deallocate(thr_act);
-
-               /* Presumably, the only reference to this activation is
-                * now held by the caller of this routine. */
-               assert(thr_act->ref_count == 1);
-#else /*AGRESSIVE_ABORT*/
-               /* If there is a lower activation in the RPC chain... */
-               if (thr_act->lower != THR_ACT_NULL) {
-                       /* ...indicate the server activation was terminated */
-                       thr_act->lower->alerts |= SERVER_TERMINATED;
-               }
-               /* Mark (and process) any orphaned activations */
-               orphan = thr_act->higher;
-#endif /*AGRESSIVE_ABORT*/
-
-               /* indicate client of orphaned chain has been terminated */
-               orphan->alerts |= CLIENT_TERMINATED;
-
-               /* 
-                * Set up posting of alert to headward portion of
-                * the RPC chain.
-                */
-               /*** fix me -- orphan act is not locked ***/
-               post_alert(orphan, ORPHANED);
-
-               /*
-                * Get attention of head of RPC chain.
-                */
-               nudge(thr_act->thread->top_act);
-               return (KERN_SUCCESS);
+       thread_lock(thread);
+       if (!(thread->state & TH_ABORT)) {
+               thread->state |= TH_ABORT;
+               install_special_handler_locked(act);
+       } else {
+               thread->state &= ~TH_ABORT_SAFELY;
        }
+       thread_unlock(thread);
+       splx(s);
 
-       /*
-        * If the target thread is the end of the chain, the thread
-        * has to be marked for abort and rip it out of any wait.
-        */
-       spl = splsched();
-       thread_lock(thr_act->thread);
-       if (thr_act->thread->top_act == thr_act) {
-           thr_act->thread->state |= TH_ABORT;
-           clear_wait_internal(thr_act->thread, THREAD_INTERRUPTED);
-           thread_unlock(thr_act->thread);
-           splx(spl);
-           install_special_handler(thr_act);
-           nudge( thr_act );
-       }
-       return KERN_SUCCESS;
+       return (KERN_SUCCESS);
 }
        
 kern_return_t
 thread_abort(
-       register thread_act_t   thr_act)
+       register thread_act_t   act)
 {
-       int             ret;
+       kern_return_t   result;
        thread_t                thread;
 
-       if (thr_act == THR_ACT_NULL || thr_act == current_act())
+       if (act == THR_ACT_NULL)
                return (KERN_INVALID_ARGUMENT);
-       /*
-        *      Lock the target thread and the current thread now,
-        *      in case thread_halt() ends up being called below.
-        */
-       thread = act_lock_thread(thr_act);
-       if (!thr_act->active) {
-               act_unlock_thread(thr_act);
-               return(KERN_TERMINATED);
+
+       thread = act_lock_thread(act);
+
+       if (!act->active) {
+               act_unlock_thread(act);
+               return (KERN_TERMINATED);
        }
 
-       ret = act_abort( thr_act, FALSE );
-       act_unlock_thread( thr_act );
-       return ret;
+       result = act_abort(act, FALSE);
+       clear_wait(thread, THREAD_INTERRUPTED);
+       act_unlock_thread(act);
+
+       return (result);
 }
 
 kern_return_t
 thread_abort_safely(
-       register thread_act_t   thr_act)
+       thread_act_t    act)
 {
        thread_t                thread;
+       kern_return_t   ret;
        spl_t                   s;
 
-       if (thr_act == THR_ACT_NULL || thr_act == current_act())
-               return(KERN_INVALID_ARGUMENT);
+       if (    act == THR_ACT_NULL )
+               return (KERN_INVALID_ARGUMENT);
 
-       thread = act_lock_thread(thr_act);
-       if (!thr_act->active) {
-               act_unlock_thread(thr_act);
-               return(KERN_TERMINATED);
-       }
-       if (thread->top_act != thr_act) {
-               act_unlock_thread(thr_act);
-               return(KERN_FAILURE);
+       thread = act_lock_thread(act);
+
+       if (!act->active) {
+               act_unlock_thread(act);
+               return (KERN_TERMINATED);
        }
+
        s = splsched();
        thread_lock(thread);
-
-       if ( thread->at_safe_point ) {
-               /*
-                * It's an abortable wait, clear it, then
-                * let the thread go and return successfully.
-                */
-               clear_wait_internal(thread, THREAD_INTERRUPTED);
-               thread_unlock(thread);
-               act_unlock_thread(thr_act);
-               splx(s);
-               return KERN_SUCCESS;
+       if (!thread->at_safe_point ||
+               clear_wait_internal(thread, THREAD_INTERRUPTED) != KERN_SUCCESS) {
+               if (!(thread->state & TH_ABORT)) {
+                       thread->state |= (TH_ABORT|TH_ABORT_SAFELY);
+                       install_special_handler_locked(act);
+               }
        }
-
-       /*
-        * if not stopped at a safepoint, just let it go and return failure.
-        */
        thread_unlock(thread);
-       act_unlock_thread(thr_act);
        splx(s);
-       return KERN_FAILURE;
+               
+       act_unlock_thread(act);
+
+       return (KERN_SUCCESS);
 }
 
 /*** backward compatibility hacks ***/
@@ -717,43 +607,60 @@ thread_set_special_port(
  */
 kern_return_t
 thread_get_state(
-       register thread_act_t   thr_act,
-       int                     flavor,
-       thread_state_t          state,  /* pointer to OUT array */
+       register thread_act_t   act,
+       int                                             flavor,
+       thread_state_t                  state,                  /* pointer to OUT array */
        mach_msg_type_number_t  *state_count)   /*IN/OUT*/
 {
-       kern_return_t           ret;
-       thread_t                thread, nthread;
+       kern_return_t           result = KERN_SUCCESS;
+       thread_t                        thread;
 
-       if (thr_act == THR_ACT_NULL || thr_act == current_act())
+       if (act == THR_ACT_NULL || act == current_act())
                return (KERN_INVALID_ARGUMENT);
 
-       thread = act_lock_thread(thr_act);
-       if (!thr_act->active) {
-               act_unlock_thread(thr_act);
-               return(KERN_TERMINATED);
+       thread = act_lock_thread(act);
+
+       if (!act->active) {
+               act_unlock_thread(act);
+               return (KERN_TERMINATED);
        }
 
-       thread_hold(thr_act);
-       while (1) {
-               if (!thread || thr_act != thread->top_act)
+       thread_hold(act);
+
+       for (;;) {
+               thread_t                        thread1;
+
+               if (    thread == THREAD_NULL           ||
+                               thread->top_act != act          )
                        break;
-               act_unlock_thread(thr_act);
-               (void)thread_stop_wait(thread);
-               nthread = act_lock_thread(thr_act);
-               if (nthread == thread)
+               act_unlock_thread(act);
+
+               if (!thread_stop(thread)) {
+                       result = KERN_ABORTED;
+                       (void)act_lock_thread(act);
+                       thread = THREAD_NULL;
+                       break;
+               }
+                       
+               thread1 = act_lock_thread(act);
+               if (thread1 == thread)
                        break;
+
                thread_unstop(thread);
-               thread = nthread;
+               thread = thread1;
        }
-       ret = act_machine_get_state(thr_act, flavor,
-                                       state, state_count);
-       if (thread && thr_act == thread->top_act)
-           thread_unstop(thread);
-       thread_release(thr_act);
-       act_unlock_thread(thr_act);
 
-       return(ret);
+       if (result == KERN_SUCCESS)
+               result = act_machine_get_state(act, flavor, state, state_count);
+
+       if (    thread != THREAD_NULL           &&
+                       thread->top_act == act          )
+               thread_unstop(thread);
+
+       thread_release(act);
+       act_unlock_thread(act);
+
+       return (result);
 }
 
 /*
@@ -762,49 +669,60 @@ thread_get_state(
  */
 kern_return_t
 thread_set_state(
-       register thread_act_t   thr_act,
-       int                     flavor,
-       thread_state_t          state,
+       register thread_act_t   act,
+       int                                             flavor,
+       thread_state_t                  state,
        mach_msg_type_number_t  state_count)
 {
-       kern_return_t           ret;
-       thread_t                thread, nthread;
+       kern_return_t           result = KERN_SUCCESS;
+       thread_t                        thread;
 
-       if (thr_act == THR_ACT_NULL || thr_act == current_act())
+       if (act == THR_ACT_NULL || act == current_act())
                return (KERN_INVALID_ARGUMENT);
-       /*
-        * We have no kernel activations, so Utah's MO fails for signals etc.
-        *
-        * If we're blocked in the kernel, use non-blocking method, else
-        * pass locked thr_act+thread in to "normal" act_[gs]et_state().
-        */
 
-       thread = act_lock_thread(thr_act);
-       if (!thr_act->active) {
-               act_unlock_thread(thr_act);
-               return(KERN_TERMINATED);
+       thread = act_lock_thread(act);
+
+       if (!act->active) {
+               act_unlock_thread(act);
+               return (KERN_TERMINATED);
        }
 
-       thread_hold(thr_act);
-       while (1) {
-               if (!thread || thr_act != thread->top_act)
+       thread_hold(act);
+
+       for (;;) {
+               thread_t                        thread1;
+
+               if (    thread == THREAD_NULL           ||
+                               thread->top_act != act          )
                        break;
-               act_unlock_thread(thr_act);
-               (void)thread_stop_wait(thread);
-               nthread = act_lock_thread(thr_act);
-               if (nthread == thread)
+               act_unlock_thread(act);
+
+               if (!thread_stop(thread)) {
+                       result = KERN_ABORTED;
+                       (void)act_lock_thread(act);
+                       thread = THREAD_NULL;
                        break;
+               }
+
+               thread1 = act_lock_thread(act);
+               if (thread1 == thread)
+                       break;
+
                thread_unstop(thread);
-               thread = nthread;
+               thread = thread1;
        }
-       ret = act_machine_set_state(thr_act, flavor,
-                                       state, state_count);
-       if (thread && thr_act == thread->top_act)
+
+       if (result == KERN_SUCCESS)
+               result = act_machine_set_state(act, flavor, state, state_count);
+
+       if (    thread != THREAD_NULL           &&
+                       thread->top_act == act          )
            thread_unstop(thread);
-       thread_release(thr_act);
-       act_unlock_thread(thr_act);
 
-       return(ret);
+       thread_release(act);
+       act_unlock_thread(act);
+
+       return (result);
 }
 
 /*
@@ -813,40 +731,58 @@ thread_set_state(
 
 kern_return_t
 thread_dup(
-       thread_act_t source_thr_act, 
-       thread_act_t target_thr_act)
+       register thread_act_t   target)
 {
-       kern_return_t           ret;
-       thread_t                thread, nthread;
+       kern_return_t           result = KERN_SUCCESS;
+       thread_act_t            self = current_act();
+       thread_t                        thread;
 
-       if (target_thr_act == THR_ACT_NULL || target_thr_act == current_act())
+       if (target == THR_ACT_NULL || target == self)
                return (KERN_INVALID_ARGUMENT);
 
-       thread = act_lock_thread(target_thr_act);
-       if (!target_thr_act->active) {
-               act_unlock_thread(target_thr_act);
-               return(KERN_TERMINATED);
+       thread = act_lock_thread(target);
+
+       if (!target->active) {
+               act_unlock_thread(target);
+               return (KERN_TERMINATED);
        }
 
-       thread_hold(target_thr_act);
-       while (1) {
-               if (!thread || target_thr_act != thread->top_act)
+       thread_hold(target);
+
+       for (;;) {
+               thread_t                        thread1;
+
+               if (    thread == THREAD_NULL           ||
+                               thread->top_act != target       )
+                       break;
+               act_unlock_thread(target);
+
+               if (!thread_stop(thread)) {
+                       result = KERN_ABORTED;
+                       (void)act_lock_thread(target);
+                       thread = THREAD_NULL;
                        break;
-               act_unlock_thread(target_thr_act);
-               (void)thread_stop_wait(thread);
-               nthread = act_lock_thread(target_thr_act);
-               if (nthread == thread)
+               }
+
+               thread1 = act_lock_thread(target);
+               if (thread1 == thread)
                        break;
+
                thread_unstop(thread);
-               thread = nthread;
+               thread = thread1;
        }
-       ret = act_thread_dup(source_thr_act, target_thr_act);
-       if (thread && target_thr_act == thread->top_act)
+
+       if (result == KERN_SUCCESS)
+               result = act_thread_dup(self, target);
+
+       if (    thread != THREAD_NULL           &&
+                       thread->top_act == target       )
            thread_unstop(thread);
-       thread_release(target_thr_act);
-       act_unlock_thread(target_thr_act);
 
-       return(ret);
+       thread_release(target);
+       act_unlock_thread(target);
+
+       return (result);
 }
 
 
@@ -858,20 +794,29 @@ thread_dup(
  */
 kern_return_t
 thread_setstatus(
-       thread_act_t            thr_act,
-       int                     flavor,
-       thread_state_t          tstate,
+       register thread_act_t   act,
+       int                                             flavor,
+       thread_state_t                  tstate,
        mach_msg_type_number_t  count)
 {
-       kern_return_t           kr;
-       thread_t                thread;
+       kern_return_t           result = KERN_SUCCESS;
+       thread_t                        thread;
 
-       thread = act_lock_thread(thr_act);
-       assert(thread);
-       assert(thread->top_act == thr_act);
-       kr = act_machine_set_state(thr_act, flavor, tstate, count);
-       act_unlock_thread(thr_act);
-       return(kr);
+       thread = act_lock_thread(act);
+
+       if (    act != current_act()                    &&
+                       (act->suspend_count == 0        ||
+                        thread == THREAD_NULL          ||
+                        (thread->state & TH_RUN)       ||
+                        thread->top_act != act)                )
+               result = KERN_FAILURE;
+
+       if (result == KERN_SUCCESS)
+               result = act_machine_set_state(act, flavor, tstate, count);
+
+       act_unlock_thread(act);
+
+       return (result);
 }
 
 /*
@@ -881,20 +826,29 @@ thread_setstatus(
  */
 kern_return_t
 thread_getstatus(
-       thread_act_t            thr_act,
-       int                     flavor,
-       thread_state_t          tstate,
+       register thread_act_t   act,
+       int                                             flavor,
+       thread_state_t                  tstate,
        mach_msg_type_number_t  *count)
 {
-       kern_return_t           kr;
-       thread_t                thread;
+       kern_return_t           result = KERN_SUCCESS;
+       thread_t                        thread;
 
-       thread = act_lock_thread(thr_act);
-       assert(thread);
-       assert(thread->top_act == thr_act);
-       kr = act_machine_get_state(thr_act, flavor, tstate, count);
-       act_unlock_thread(thr_act);
-       return(kr);
+       thread = act_lock_thread(act);
+
+       if (    act != current_act()                    &&
+                       (act->suspend_count == 0        ||
+                        thread == THREAD_NULL          ||
+                        (thread->state & TH_RUN)       ||
+                        thread->top_act != act)                )
+               result = KERN_FAILURE;
+
+       if (result == KERN_SUCCESS)
+               result = act_machine_get_state(act, flavor, tstate, count);
+
+       act_unlock_thread(act);
+
+       return (result);
 }
 
 /*
@@ -912,6 +866,7 @@ act_init()
                        ACT_MAX * sizeof(struct thread_activation), /* XXX */
                        ACT_CHUNK * sizeof(struct thread_activation),
                        "activations");
+       first_act = TRUE;
        act_machine_init();
 }
 
@@ -927,7 +882,11 @@ act_create(task_t task,
        int rc;
        vm_map_t map;
 
-       thr_act = (thread_act_t)zalloc(thr_act_zone);
+       if (first_act) {
+               thr_act = &pageout_act;
+               first_act = FALSE;
+       } else
+               thr_act = (thread_act_t)zalloc(thr_act_zone);
        if (thr_act == 0)
                return(KERN_RESOURCE_SHORTAGE);
 
@@ -940,6 +899,9 @@ act_create(task_t task,
        /* Start by zeroing everything; then init non-zero items only */
        bzero((char *)thr_act, sizeof(*thr_act));
 
+       if (thr_act == &pageout_act)
+               thr_act->thread = &pageout_thread;
+
 #ifdef MACH_BSD
        {
                /*
@@ -948,8 +910,9 @@ act_create(task_t task,
                 * handling trivial
                 * uthread_alloc() will bzero the storage allocated.
                 */
-               extern void *uthread_alloc(void);
-               thr_act->uthread = uthread_alloc();
+               extern void *uthread_alloc(task_t, thread_act_t);
+
+               thr_act->uthread = uthread_alloc(task, thr_act);
                if(thr_act->uthread == 0) {
                        /* Put the thr_act back on the thr_act zone */
                        zfree(thr_act_zone, (vm_offset_t)thr_act);
@@ -969,17 +932,6 @@ act_create(task_t task,
        thr_act->task = task;
        task_reference(task);
 
-       /* Initialize sigbufp for High-Watermark buffer allocation */
-        thr_act->r_sigbufp = (routine_descriptor_t) &thr_act->r_sigbuf;
-        thr_act->r_sigbuf_size = sizeof(thr_act->r_sigbuf);
-
-#if    THREAD_SWAPPER
-       thr_act->swap_state = TH_SW_IN;
-#if    MACH_ASSERT
-       thr_act->kernel_stack_swapped_in = TRUE;
-#endif /* MACH_ASSERT */
-#endif /* THREAD_SWAPPER */
-
        /* special_handler will always be last on the returnhandlers list.  */
        thr_act->special_handler.next = 0;
        thr_act->special_handler.handler = special_handler;
@@ -1013,10 +965,6 @@ act_create(task_t task,
 
        /* Inline vm_map_reference cause we don't want to increment res_count */
        mutex_lock(&map->s_lock);
-#if    TASK_SWAPPER
-       assert(map->res_count > 0);
-       assert(map->ref_count >= map->res_count);
-#endif /* TASK_SWAPPER */
        map->ref_count++;
        mutex_unlock(&map->s_lock);
 
@@ -1045,28 +993,23 @@ act_free(thread_act_t thr_act)
        thread_t        thr;
        vm_map_t        map;
        unsigned int    ref;
+       void * task_proc;
 
 #if    MACH_ASSERT
        if (watchacts & WA_EXIT)
-               printf("act_free(%x(%d)) thr=%x tsk=%x(%d) pport=%x%sactive\n",
+               printf("act_free(%x(%d)) thr=%x tsk=%x(%d) %sactive\n",
                        thr_act, thr_act->ref_count, thr_act->thread,
                        thr_act->task,
                        thr_act->task ? thr_act->task->ref_count : 0,
-                       thr_act->pool_port,
                        thr_act->active ? " " : " !");
 #endif /* MACH_ASSERT */
 
-
-#if    THREAD_SWAPPER
-       assert(thr_act->kernel_stack_swapped_in);
-#endif /* THREAD_SWAPPER */
-
        assert(!thr_act->active);
-       assert(!thr_act->pool_port);
 
        task = thr_act->task;
        task_lock(task);
 
+       task_proc = task->bsd_info;
        if (thr = thr_act->thread) {
                time_value_t    user_time, system_time;
 
@@ -1081,15 +1024,6 @@ act_free(thread_act_t thr_act)
                queue_remove(&task->thr_acts, thr_act, thread_act_t, thr_acts);
                thr_act->thr_acts.next = NULL;
                task->thr_act_count--;
-
-#if     THREAD_SWAPPER
-               /*
-                * Thread is supposed to be unswappable by now...
-                */
-               assert(thr_act->swap_state == TH_SW_UNSWAPPABLE ||
-                      !thread_swap_unwire_stack);
-#endif  /* THREAD_SWAPPER */
-
                task->res_act_count--;
                task_unlock(task);
                task_deallocate(task);
@@ -1105,7 +1039,6 @@ act_free(thread_act_t thr_act)
                task_deallocate(task);
        }
 
-       sigbuf_dealloc(thr_act);
        act_prof_deallocate(thr_act);
        ipc_thr_act_terminate(thr_act);
 
@@ -1116,10 +1049,6 @@ act_free(thread_act_t thr_act)
         */
        map = thr_act->map;
        mutex_lock(&map->s_lock);
-#if    TASK_SWAPPER
-       assert(map->res_count >= 0);
-       assert(map->ref_count > map->res_count);
-#endif /* TASK_SWAPPER */
        ref = --map->ref_count;
        mutex_unlock(&map->s_lock);
        if (ref == 0)
@@ -1131,10 +1060,11 @@ act_free(thread_act_t thr_act)
                 * Free uthread BEFORE the bzero.
                 * Not doing so will result in a leak.
                 */
-               extern void uthread_free(void *);
+               extern void uthread_free(task_t, void *, void *);
+
                void *ut = thr_act->uthread;
                thr_act->uthread = 0;
-               uthread_free(ut);
+               uthread_free(task, ut, task_proc);
        }
 #endif  /* MACH_BSD */   
 
@@ -1151,9 +1081,7 @@ act_free(thread_act_t thr_act)
  * act_attach  - Attach an thr_act to the top of a thread ("push the stack").
  *
  * The thread_shuttle must be either the current one or a brand-new one.
- * Assumes the thr_act is active but not in use, also, that if it is
- * attached to an thread_pool (i.e. the thread_pool pointer is nonzero),
- * the thr_act has already been taken off the thread_pool's list.
+ * Assumes the thr_act is active but not in use.
  *
  * Already locked: thr_act plus "appropriate" thread-related locks
  * (see act_lock_thread()).
@@ -1221,8 +1149,6 @@ act_detach(
        cur_act->ref_count--;
        assert(cur_act->ref_count > 0);
 
-       thread_pool_put_act(cur_act);
-
 #if    MACH_ASSERT
        cur_act->lower = cur_act->higher = THR_ACT_NULL; 
        if (cur_thread->top_act)
@@ -1234,65 +1160,39 @@ act_detach(
 
 
 /*
- * Synchronize a thread operation with RPC.  Called with nothing
- * locked.   Returns with thr_act locked, plus one of four
- * combinations of other locks held:
- *     none - for new activation not yet associated with thread_pool
- *             or shuttle
- *     rpc_lock(thr_act->thread) only - for base activation (one
- *             without pool_port)
- *     ip_lock(thr_act->pool_port) only - for empty activation (one
- *             with no associated shuttle)
- *     both locks - for "active" activation (has shuttle, lives
- *             on thread_pool)
- * If thr_act has an associated shuttle, this function returns
- * its address.  Otherwise it returns zero.
+ * Synchronize a thread operation with migration.
+ * Called with nothing locked.
+ * Returns with thr_act locked.
  */
 thread_t
 act_lock_thread(
        thread_act_t thr_act)
 {
-       ipc_port_t pport;
 
        /*
-        * Allow the shuttle cloning code (q.v., when it
-        * exists :-}) to obtain ip_lock()'s while holding
-        * an rpc_lock().
+        * JMM - We have moved away from explicit RPC locks
+        * and towards a generic migration approach.  The wait
+        * queue lock will be the point of synchronization for
+        * the shuttle linkage when this is rolled out.  Until
+        * then, just lock the act.
         */
-       while (1) {
-               act_lock(thr_act);
-               pport = thr_act->pool_port;
-               if (!pport || ip_lock_try(pport)) {
-                       if (!thr_act->thread)
-                               break;
-                       if (rpc_lock_try(thr_act->thread))
-                               break;
-                       if (pport)
-                               ip_unlock(pport);
-               }
-               act_unlock(thr_act);
-               mutex_pause();
-       }
+       act_lock(thr_act);
        return (thr_act->thread);
 }
 
 /*
- * Unsynchronize with RPC (i.e., undo an act_lock_thread() call).
+ * Unsynchronize with migration (i.e., undo an act_lock_thread() call).
  * Called with thr_act locked, plus thread locks held that are
  * "correct" for thr_act's state.  Returns with nothing locked.
  */
 void
 act_unlock_thread(thread_act_t thr_act)
 {
-       if (thr_act->thread)
-               rpc_unlock(thr_act->thread);
-       if (thr_act->pool_port)
-               ip_unlock(thr_act->pool_port);
        act_unlock(thr_act);
 }
 
 /*
- * Synchronize with RPC given a pointer to a shuttle (instead of an
+ * Synchronize with migration given a pointer to a shuttle (instead of an
  * activation).  Called with nothing locked; returns with all
  * "appropriate" thread-related locks held (see act_lock_thread()).
  */
@@ -1303,19 +1203,10 @@ thread_lock_act(
        thread_act_t    thr_act;
 
        while (1) {
-               rpc_lock(thread);
                thr_act = thread->top_act;
                if (!thr_act)
                        break;
                if (!act_lock_try(thr_act)) {
-                       rpc_unlock(thread);
-                       mutex_pause();
-                       continue;
-               }
-               if (thr_act->pool_port &&
-                       !ip_lock_try(thr_act->pool_port)) {
-                       rpc_unlock(thread);
-                       act_unlock(thr_act);
                        mutex_pause();
                        continue;
                }
@@ -1325,9 +1216,8 @@ thread_lock_act(
 }
 
 /*
- * Unsynchronize with RPC starting from a pointer to a shuttle.
- * Called with RPC-related locks held that are appropriate to
- * shuttle's state; any activation is also locked.
+ * Unsynchronize with an activation starting from a pointer to
+ * a shuttle.
  */
 void
 thread_unlock_act(
@@ -1336,11 +1226,8 @@ thread_unlock_act(
        thread_act_t    thr_act;
 
        if (thr_act = thread->top_act) {
-               if (thr_act->pool_port)
-                       ip_unlock(thr_act->pool_port);
                act_unlock(thr_act);
        }
-       rpc_unlock(thread);
 }
 
 /*
@@ -1348,7 +1235,7 @@ thread_unlock_act(
  *
  * If a new activation is given, switch to it. If not,
  * switch to the lower activation (pop). Returns the old
- * activation. This is for RPC support.
+ * activation. This is for migration support.
  */
 thread_act_t
 switch_act( 
@@ -1379,12 +1266,7 @@ switch_act(
        }
 
        assert(new != THR_ACT_NULL);
-#if    THREAD_SWAPPER
-       assert(new->swap_state != TH_SW_OUT &&
-              new->swap_state != TH_SW_COMING_IN);
-#endif /* THREAD_SWAPPER */
-
-        assert(cpu_data[cpu].active_thread == thread);
+       assert(cpu_to_processor(cpu)->cpu_data->active_thread == thread);
        active_kloaded[cpu] = (new->kernel_loaded) ? new : 0;
 
        /* This is where all the work happens */
@@ -1441,221 +1323,61 @@ install_special_handler(
  */
 void
 install_special_handler_locked(
-       thread_act_t    thr_act)
+       thread_act_t                            act)
 {
+       thread_t                thread = act->thread;
        ReturnHandler   **rh;
-       thread_t        thread = thr_act->thread;
 
        /* The work handler must always be the last ReturnHandler on the list,
           because it can do tricky things like detach the thr_act.  */
-       for (rh = &thr_act->handlers; *rh; rh = &(*rh)->next)
-               /* */ ;
-       if (rh != &thr_act->special_handler.next) {
-               *rh = &thr_act->special_handler;
-       }
-       if (thread && thr_act == thread->top_act) {
+       for (rh = &act->handlers; *rh; rh = &(*rh)->next)
+               continue;
+       if (rh != &act->special_handler.next)
+               *rh = &act->special_handler;
+
+       if (act == thread->top_act) {
                /*
                 * Temporarily undepress, so target has
                 * a chance to do locking required to
                 * block itself in special_handler().
                 */
-               if (thread->depress_priority >= 0) {
-                       thread->priority = thread->depress_priority;
-
-                       /*
-                        * Use special value -2 to indicate need
-                        * to redepress priority in special_handler
-                        * as thread blocks
-                        */
-                       thread->depress_priority = -2;
-                       compute_priority(thread, FALSE);
-               }       
+               if (thread->sched_mode & TH_MODE_ISDEPRESSED)
+                       compute_priority(thread, TRUE);
        }
-       act_set_apc(thr_act);
-}
 
-/*
- * JMM -
- * These two routines will be enhanced over time to call the general handler registration
- * mechanism used by special handlers and alerts.  They are hack in for now to avoid
- * having to export the gory details of ASTs to the BSD code right now.
- */
-extern thread_apc_handler_t bsd_ast;
+       thread_ast_set(act, AST_APC);
+       if (act == current_act())
+               ast_propagate(act->ast);
+       else {
+               processor_t             processor = thread->last_processor;
+
+               if (    processor != PROCESSOR_NULL                                             &&
+                               processor->state == PROCESSOR_RUNNING                   &&
+                               processor->cpu_data->active_thread == thread    )
+                       cause_ast_check(processor);
+       }
+}
 
 kern_return_t
 thread_apc_set(
-       thread_act_t thr_act,
-       thread_apc_handler_t apc)
+       thread_act_t                    act,
+       thread_apc_handler_t    apc)
 {
+       extern thread_apc_handler_t     bsd_ast;
+
        assert(apc == bsd_ast);
-       thread_ast_set(thr_act, AST_BSD);
-       if (thr_act == current_act())
-               ast_propagate(thr_act->ast);
-       return KERN_SUCCESS;
+       return (KERN_FAILURE);
 }
 
 kern_return_t
 thread_apc_clear(
-       thread_act_t thr_act,
-       thread_apc_handler_t apc)
+       thread_act_t                    act,
+       thread_apc_handler_t    apc)
 {
-       assert(apc == bsd_ast);
-       thread_ast_clear(thr_act, AST_BSD);
-       if (thr_act == current_act())
-               ast_off(AST_BSD);
-       return KERN_SUCCESS;
-}
-
-/*
- * act_set_thread_pool - Assign an activation to a specific thread_pool.
- * Fails if the activation is already assigned to another pool.
- * If thread_pool == 0, we remove the thr_act from its thread_pool.
- *
- * Called the port containing thread_pool already locked.
- * Returns the same way.
- */
-kern_return_t act_set_thread_pool(
-       thread_act_t    thr_act,
-       ipc_port_t      pool_port)
-{
-       thread_pool_t   thread_pool;
-
-#if    MACH_ASSERT
-       if (watchacts & WA_ACT_LNK)
-               printf("act_set_thread_pool: %x(%d) -> %x\n",
-                       thr_act, thr_act->ref_count, thread_pool);
-#endif /* MACH_ASSERT */
-
-       if (pool_port == 0) {
-               thread_act_t *lact;
-
-               if (thr_act->pool_port == 0)
-                       return KERN_SUCCESS;
-               thread_pool = &thr_act->pool_port->ip_thread_pool;
-
-               for (lact = &thread_pool->thr_acts; *lact;
-                                       lact = &((*lact)->thread_pool_next)) {
-                       if (thr_act == *lact) {
-                               *lact = thr_act->thread_pool_next;
-                               break;
-                       }
-               }
-               act_lock(thr_act);
-               thr_act->pool_port = 0;
-               thr_act->thread_pool_next = 0;
-               act_unlock(thr_act);
-               act_deallocate(thr_act);
-               return KERN_SUCCESS;
-       }
-       if (thr_act->pool_port != pool_port) {
-               thread_pool = &pool_port->ip_thread_pool;
-               if (thr_act->pool_port != 0) {
-#if    MACH_ASSERT
-                       if (watchacts & WA_ACT_LNK)
-                           printf("act_set_thread_pool found %x!\n",
-                                                       thr_act->pool_port);
-#endif /* MACH_ASSERT */
-                       return(KERN_FAILURE);
-               }
-               act_lock(thr_act);
-               thr_act->pool_port = pool_port;
-
-               /* The pool gets a ref to the activation -- have
-                * to inline operation because thr_act is already
-                * locked.
-                */
-               act_locked_act_reference(thr_act);
-
-               /* If it is available,
-                * add it to the thread_pool's available-activation list.
-                */
-               if ((thr_act->thread == 0) && (thr_act->suspend_count == 0)) {
-                       thr_act->thread_pool_next = thread_pool->thr_acts;
-                       pool_port->ip_thread_pool.thr_acts = thr_act;
-                       if (thread_pool->waiting)
-                               thread_pool_wakeup(thread_pool);
-               }
-               act_unlock(thr_act);
-       }
-
-       return KERN_SUCCESS;
-}
-
-/*
- * act_locked_act_set_thread_pool- Assign activation to a specific thread_pool.
- * Fails if the activation is already assigned to another pool.
- * If thread_pool == 0, we remove the thr_act from its thread_pool.
- *
- * Called the port containing thread_pool already locked.
- * Also called with the thread activation locked.
- * Returns the same way.
- *
- * This routine is the same as `act_set_thread_pool()' except that it does
- * not call `act_deallocate(),' which unconditionally tries to obtain the
- * thread activation lock.
- */
-kern_return_t act_locked_act_set_thread_pool(
-       thread_act_t    thr_act,
-       ipc_port_t      pool_port)
-{
-       thread_pool_t   thread_pool;
-
-#if    MACH_ASSERT
-       if (watchacts & WA_ACT_LNK)
-               printf("act_set_thread_pool: %x(%d) -> %x\n",
-                       thr_act, thr_act->ref_count, thread_pool);
-#endif /* MACH_ASSERT */
-
-       if (pool_port == 0) {
-               thread_act_t *lact;
-
-               if (thr_act->pool_port == 0)
-                       return KERN_SUCCESS;
-               thread_pool = &thr_act->pool_port->ip_thread_pool;
-
-               for (lact = &thread_pool->thr_acts; *lact;
-                                       lact = &((*lact)->thread_pool_next)) {
-                       if (thr_act == *lact) {
-                               *lact = thr_act->thread_pool_next;
-                               break;
-                       }
-               }
-
-               thr_act->pool_port = 0;
-               thr_act->thread_pool_next = 0;
-               act_locked_act_deallocate(thr_act);
-               return KERN_SUCCESS;
-       }
-       if (thr_act->pool_port != pool_port) {
-               thread_pool = &pool_port->ip_thread_pool;
-               if (thr_act->pool_port != 0) {
-#if    MACH_ASSERT
-                       if (watchacts & WA_ACT_LNK)
-                           printf("act_set_thread_pool found %x!\n",
-                                                       thr_act->pool_port);
-#endif /* MACH_ASSERT */
-                       return(KERN_FAILURE);
-               }
-               thr_act->pool_port = pool_port;
-
-               /* The pool gets a ref to the activation -- have
-                * to inline operation because thr_act is already
-                * locked.
-                */
-               act_locked_act_reference(thr_act);
-
-               /* If it is available,
-                * add it to the thread_pool's available-activation list.
-                */
-               if ((thr_act->thread == 0) && (thr_act->suspend_count == 0)) {
-                       thr_act->thread_pool_next = thread_pool->thr_acts;
-                       pool_port->ip_thread_pool.thr_acts = thr_act;
-                       if (thread_pool->waiting)
-                               thread_pool_wakeup(thread_pool);
-               }
-       }
+       extern thread_apc_handler_t     bsd_ast;
 
-       return KERN_SUCCESS;
+       assert(apc == bsd_ast);
+       return (KERN_FAILURE);
 }
 
 /*
@@ -1667,52 +1389,46 @@ kern_return_t act_locked_act_set_thread_pool(
  *
  * This is called by system-dependent code when it detects that
  * thr_act->handlers is non-null while returning into user mode.
- * Activations linked onto an thread_pool always have null thr_act->handlers,
- * so RPC entry paths need not check it.
  */
-void act_execute_returnhandlers(
-       void)
+void
+act_execute_returnhandlers(void)
 {
-       spl_t           s;
-       thread_t        thread;
-       thread_act_t    thr_act = current_act();
+       thread_act_t    act = current_act();
 
 #if    MACH_ASSERT
        if (watchacts & WA_ACT_HDLR)
-               printf("execute_rtn_hdlrs: thr_act=%x\n", thr_act);
+               printf("execute_rtn_hdlrs: act=%x\n", act);
 #endif /* MACH_ASSERT */
 
-       s = splsched();
-       act_clr_apc(thr_act);
+       thread_ast_clear(act, AST_APC);
        spllo();
-       while (1) {
-               ReturnHandler *rh;
 
-               /* Grab the next returnhandler */
-               thread = act_lock_thread(thr_act);
+       for (;;) {
+               ReturnHandler   *rh;
+               thread_t                thread = act_lock_thread(act);
+
                (void)splsched();
                thread_lock(thread);
-               rh = thr_act->handlers;
+               rh = act->handlers;
                if (!rh) {
                        thread_unlock(thread);
-                       splx(s);
-                       act_unlock_thread(thr_act);
+                       spllo();
+                       act_unlock_thread(act);
                        return;
                }
-               thr_act->handlers = rh->next;
+               act->handlers = rh->next;
                thread_unlock(thread);
                spllo();
-               act_unlock_thread(thr_act);
+               act_unlock_thread(act);
 
 #if    MACH_ASSERT
                if (watchacts & WA_ACT_HDLR)
-                   printf( (rh == &thr_act->special_handler) ?
-                       "\tspecial_handler\n" : "\thandler=%x\n",
-                                   rh->handler);
+                   printf( (rh == &act->special_handler) ?
+                       "\tspecial_handler\n" : "\thandler=%x\n", rh->handler);
 #endif /* MACH_ASSERT */
 
                /* Execute it */
-               (*rh->handler)(rh, thr_act);
+               (*rh->handler)(rh, act);
        }
 }
 
@@ -1728,28 +1444,28 @@ void act_execute_returnhandlers(
 void
 special_handler_continue(void)
 {
-       thread_act_t cur_act = current_act();
-       thread_t thread = cur_act->thread;
-       spl_t s;
+       thread_act_t            self = current_act();
 
-       if (cur_act->suspend_count)
-               install_special_handler(cur_act);
+       if (self->suspend_count > 0)
+               install_special_handler(self);
        else {
-               s = splsched();
+               thread_t                thread = self->thread;
+               spl_t                   s = splsched();
+
                thread_lock(thread);
-               if (thread->depress_priority == -2) {
-                       /*
-                        * We were temporarily undepressed by
-                        * install_special_handler; restore priority
-                        * depression.
-                        */
-                       thread->depress_priority = thread->priority;
-                       thread->priority = thread->sched_pri = DEPRESSPRI;
+               if (thread->sched_mode & TH_MODE_ISDEPRESSED) {
+                       processor_t             myprocessor = thread->last_processor;
+
+                       thread->sched_pri = DEPRESSPRI;
+                       myprocessor->current_pri = thread->sched_pri;
+                       thread->sched_mode &= ~TH_MODE_PREEMPT;
                }
                thread_unlock(thread);
                splx(s);
        }
+
        thread_exception_return();
+       /*NOTREACHED*/
 }
 
 /*
@@ -1759,28 +1475,16 @@ special_handler_continue(void)
 void
 special_handler(
        ReturnHandler   *rh,
-       thread_act_t    cur_act)
+       thread_act_t    self)
 {
-       spl_t           s;
-       thread_t        lthread;
-       thread_t        thread = act_lock_thread(cur_act);
-       unsigned        alert_bits;
-       exception_data_type_t
-                       codes[EXCEPTION_CODE_MAX];
-       kern_return_t   kr;
-       kern_return_t   exc_kr;
+       thread_t                thread = act_lock_thread(self);
+       spl_t                   s;
 
        assert(thread != THREAD_NULL);
-#if    MACH_ASSERT
-       if (watchacts & WA_ACT_HDLR)
-           printf("\t\tspecial_handler(thr_act=%x(%d))\n", cur_act,
-                               (cur_act ? cur_act->ref_count : 0));
-#endif /* MACH_ASSERT */
 
        s = splsched();
-
        thread_lock(thread);
-       thread->state &= ~TH_ABORT;     /* clear any aborts */
+       thread->state &= ~(TH_ABORT|TH_ABORT_SAFELY);   /* clear any aborts */
        thread_unlock(thread);
        splx(s);
 
@@ -1788,144 +1492,29 @@ special_handler(
         * If someone has killed this invocation,
         * invoke the return path with a terminated exception.
         */
-       if (!cur_act->active) {
-               act_unlock_thread(cur_act);
+       if (!self->active) {
+               act_unlock_thread(self);
                act_machine_return(KERN_TERMINATED);
        }
 
-#ifdef CALLOUT_RPC_MODEL
-       /*
-        * JMM - We don't intend to support this RPC model in Darwin.
-        * We will support inheritance through chains of activations
-        * on shuttles, but it will be universal and not just for RPC.
-        * As such, each activation will always have a base shuttle.
-        * Our RPC model will probably even support the notion of
-        * alerts (thrown up the chain of activations to affect the
-        * work done on our behalf), but the unlinking of the shuttles
-        * will be completely difference because we will never have
-        * to clone them.
-        */
-
-       /* strip server terminated bit */
-       alert_bits = cur_act->alerts & (~SERVER_TERMINATED);
-
-       /* clear server terminated bit */
-       cur_act->alerts &= ~SERVER_TERMINATED;
-
-       if ( alert_bits ) {
-               /*
-                * currently necessary to coordinate with the exception 
-                * code -fdr
-                */
-               act_unlock_thread(cur_act);
-
-               /* upcall exception/alert port */
-               codes[0] = alert_bits;
-
-               /*
-                * Exception makes a lot of assumptions. If there is no
-                * exception handler or the exception reply is broken, the 
-                * thread will be terminated and exception will not return. If
-                * we decide we don't like that behavior, we need to check
-                * for the existence of an exception port before we call 
-                * exception.
-                */
-               exc_kr = exception( EXC_RPC_ALERT, codes, 1 );
-
-               /* clear the orphaned and time constraint indications */
-               cur_act->alerts &= ~(ORPHANED | TIME_CONSTRAINT_UNSATISFIED);
-
-               /* if this orphaned activation should be terminated... */
-               if (exc_kr == KERN_RPC_TERMINATE_ORPHAN) {
-                       /*
-                        * ... terminate the activation
-                        *
-                        * This is done in two steps.  First, the activation is
-                        * disabled (prepared for termination); second, the
-                        * `special_handler()' is executed again -- this time
-                        * to terminate the activation.
-                        * (`act_disable_task_locked()' arranges for the
-                        * additional execution of the `special_handler().')
-                        */
-
-#if    THREAD_SWAPPER
-                       thread_swap_disable(cur_act);
-#endif /* THREAD_SWAPPER */
-
-                       /* acquire appropriate locks */
-                       task_lock(cur_act->task);
-                       act_lock_thread(cur_act);
-
-                       /* detach the activation from its task */
-                       kr = act_disable_task_locked(cur_act);
-                       assert( kr == KERN_SUCCESS );
-
-                       /* release locks */
-                       task_unlock(cur_act->task);
-               }
-               else {
-                       /* acquire activation lock again (released below) */
-                       act_lock_thread(cur_act);
-                       s = splsched();
-                       thread_lock(thread);
-                       if (thread->depress_priority == -2) {
-                               /*
-                                * We were temporarily undepressed by
-                                * install_special_handler; restore priority
-                                * depression.
-                                */
-                               thread->depress_priority = thread->priority;
-                               thread->priority = thread->sched_pri = DEPRESSPRI;
-                       }
-                       thread_unlock(thread);
-                       splx(s);
-               }
-       }
-#endif /* CALLOUT_RPC_MODEL */
-
        /*
         * If we're suspended, go to sleep and wait for someone to wake us up.
         */
-       if (cur_act->suspend_count) {
-               if( cur_act->handlers == NULL ) {
-                       assert_wait((event_t)&cur_act->suspend_count,
-                                   THREAD_ABORTSAFE);
-                       act_unlock_thread(cur_act);
+       if (self->suspend_count > 0) {
+               if (self->handlers == NULL) {
+                       assert_wait(&self->suspend_count, THREAD_ABORTSAFE);
+                       act_unlock_thread(self);
                        thread_block(special_handler_continue);
                        /* NOTREACHED */
                }
-               special_handler_continue();
-       }
 
-       act_unlock_thread(cur_act);
-}
+               act_unlock_thread(self);
 
-/*
- * Try to nudge a thr_act into executing its returnhandler chain.
- * Ensures that the activation will execute its returnhandlers
- * before it next executes any of its user-level code.
- *
- * Called with thr_act's act_lock() and "appropriate" thread-related
- * locks held.  (See act_lock_thread().)  Returns same way.
- */
-void
-nudge(thread_act_t     thr_act)
-{
-#if    MACH_ASSERT
-       if (watchacts & WA_ACT_HDLR)
-           printf("\tact_%x: nudge(%x)\n", current_act(), thr_act);
-#endif /* MACH_ASSERT */
-
-       /*
-        * Don't need to do anything at all if this thr_act isn't the topmost.
-        */
-       if (thr_act->thread && thr_act->thread->top_act == thr_act) {
-               /*
-                * If it's suspended, wake it up. 
-                * This should nudge it even on another CPU.
-                */
-               thread_wakeup((event_t)&thr_act->suspend_count);
+               special_handler_continue();
+               /*NOTREACHED*/
        }
+
+       act_unlock_thread(self);
 }
 
 /*
@@ -1940,52 +1529,27 @@ act_user_to_kernel(
 }
 
 /*
- * Already locked: thr_act->task, RPC-related locks for thr_act
+ * Already locked: activation (shuttle frozen within)
  *
- * Detach an activation from its task, and prepare it to terminate
+ * Mark an activation inactive, and prepare it to terminate
  * itself.
  */
-kern_return_t
-act_disable_task_locked(
+static void
+act_disable(
        thread_act_t    thr_act)
 {
-       thread_t        thread = thr_act->thread;
-       task_t          task = thr_act->task;
 
 #if    MACH_ASSERT
        if (watchacts & WA_EXIT) {
-               printf("act_%x: act_disable_tl(thr_act=%x(%d))%sactive task=%x(%d)",
+               printf("act_%x: act_disable_tl(thr_act=%x(%d))%sactive",
                               current_act(), thr_act, thr_act->ref_count,
-                              (thr_act->active ? " " : " !"),
-                              thr_act->task, thr_act->task? thr_act->task->ref_count : 0);
-               if (thr_act->pool_port)
-                       printf(", pool_port %x", thr_act->pool_port);
+                                       (thr_act->active ? " " : " !"));
                printf("\n");
                (void) dump_act(thr_act);
        }
 #endif /* MACH_ASSERT */
 
-       /* This will allow no more control ops on this thr_act. */
        thr_act->active = 0;
-       ipc_thr_act_disable(thr_act);
-
-       /* Clean-up any ulocks that are still owned by the thread
-        * activation (acquired but not released or handed-off).
-        */
-       act_ulock_release_all(thr_act);
-
-       /* When the special_handler gets executed,
-        * it will see the terminated condition and exit
-        * immediately.
-        */
-       install_special_handler(thr_act);
-
-
-       /* If the target happens to be suspended,
-        * give it a nudge so it can exit.
-        */
-       if (thr_act->suspend_count)
-               nudge(thr_act);
 
        /* Drop the thr_act reference taken for being active.
         * (There is still at least one reference left:
@@ -1993,8 +1557,6 @@ act_disable_task_locked(
         * Inline the deallocate because thr_act is locked.
         */
        act_locked_act_deallocate(thr_act);
-
-       return(KERN_SUCCESS);
 }
 
 /*
@@ -2060,11 +1622,16 @@ void set_state_handler(ReturnHandler *rh, thread_act_t thr_act);
  * thread-related locks held.  (See act_lock_thread().)
  */
 kern_return_t
-get_set_state(thread_act_t thr_act, int flavor, thread_state_t state, int *pcount,
-                       void (*handler)(ReturnHandler *rh, thread_act_t thr_act))
+get_set_state(
+       thread_act_t            act,
+       int                                     flavor,
+       thread_state_t          state,
+       int                                     *pcount,
+       void                            (*handler)(
+                                                       ReturnHandler   *rh,
+                                                       thread_act_t     act))
 {
-       GetSetState gss;
-       spl_t s;
+       GetSetState                     gss;
 
        /* Initialize a small parameter structure */
        gss.rh.handler = handler;
@@ -2074,17 +1641,15 @@ get_set_state(thread_act_t thr_act, int flavor, thread_state_t state, int *pcoun
        gss.result = KERN_ABORTED;      /* iff wait below is interrupted */
 
        /* Add it to the thr_act's return handler list */
-       gss.rh.next = thr_act->handlers;
-       thr_act->handlers = &gss.rh;
+       gss.rh.next = act->handlers;
+       act->handlers = &gss.rh;
 
-       s = splsched();
-       act_set_apc(thr_act);
-       splx(s);
+       act_set_apc(act);
 
 #if    MACH_ASSERT
        if (watchacts & WA_ACT_HDLR) {
-           printf("act_%x: get_set_state(thr_act=%x flv=%x state=%x ptr@%x=%x)",
-                   current_act(), thr_act, flavor, state,
+           printf("act_%x: get_set_state(act=%x flv=%x state=%x ptr@%x=%x)",
+                   current_act(), act, flavor, state,
                    pcount, (pcount ? *pcount : 0));
            printf((handler == get_state_handler ? "get_state_hdlr\n" :
                    (handler == set_state_handler ? "set_state_hdlr\n" :
@@ -2092,23 +1657,39 @@ get_set_state(thread_act_t thr_act, int flavor, thread_state_t state, int *pcoun
        }
 #endif /* MACH_ASSERT */
 
-       assert(thr_act->thread);        /* Callers must ensure these */
-       assert(thr_act != current_act());
+       assert(act->thread);
+       assert(act != current_act());
+
        for (;;) {
-               nudge(thr_act);
+               wait_result_t           result;
+
+               if (    act->inited                                             &&
+                               act->thread->top_act == act             )
+                               thread_wakeup_one(&act->suspend_count);
+
                /*
                 * Wait must be interruptible to avoid deadlock (e.g.) with
                 * task_suspend() when caller and target of get_set_state()
                 * are in same task.
                 */
-               assert_wait((event_t)&gss, THREAD_ABORTSAFE);
-               act_unlock_thread(thr_act);
-               thread_block((void (*)(void))0);
-               if (gss.result != KERN_ABORTED)
+               result = assert_wait(&gss, THREAD_ABORTSAFE);
+               act_unlock_thread(act);
+
+               if (result == THREAD_WAITING)
+                       result = thread_block(THREAD_CONTINUE_NULL);
+
+               assert(result != THREAD_WAITING);
+
+               if (gss.result != KERN_ABORTED) {
+                       assert(result != THREAD_INTERRUPTED);
                        break;
+               }
+
+               /* JMM - What about other aborts (like BSD signals)? */
                if (current_act()->handlers)
                        act_execute_returnhandlers();
-               act_lock_thread(thr_act);
+
+               act_lock_thread(act);
        }
 
 #if    MACH_ASSERT
@@ -2117,7 +1698,7 @@ get_set_state(thread_act_t thr_act, int flavor, thread_state_t state, int *pcoun
                            current_act(), gss.result);
 #endif /* MACH_ASSERT */
 
-       return gss.result;
+       return (gss.result);
 }
 
 void
@@ -2203,47 +1784,58 @@ act_get_state(thread_act_t thr_act, int flavor, thread_state_t state,
     return(act_get_state_locked(thr_act, flavor, state, pcount));
 }
 
-/*
- * These two should be called at splsched()
- * Set/clear indicator to run APC (layered on ASTs)
- */
 void
-act_set_apc(thread_act_t thr_act)
+act_set_astbsd(
+       thread_act_t    act)
 {
-
-       processor_t prssr;
-       thread_t thread;
-       
-       mp_disable_preemption();
+       spl_t                   s = splsched();
        
-       thread_ast_set(thr_act, AST_APC);
-       if (thr_act == current_act()) {
-               ast_propagate(thr_act->ast);
-               mp_enable_preemption();
-               return;                                                 /* If we are current act, we can't be on the other processor so leave now */
+       if (act == current_act()) {
+               thread_ast_set(act, AST_BSD);
+               ast_propagate(act->ast);
        }
+       else {
+               thread_t                thread = act->thread;
+               processor_t             processor;
 
-/*
- *     Here we want to make sure that the apc is taken quickly.  Therefore, we check
- *     if, and where, the activation is running.  If it is not running, we don't need to do 
- *     anything.  If it is, we need to signal the other processor to trigger it to 
- *     check the asts.  Note that there is a race here and we may end up sending a signal
- *     after the thread has been switched off.  Hopefully this is no big deal.
- */
-
-       thread = thr_act->thread;                       /* Get the thread for the signaled activation */
-       prssr = thread->last_processor;         /* get the processor it was last on */
-       if(prssr && (cpu_data[prssr->slot_num].active_thread == thread)) {      /* Is the thread active on its processor? */
-               cause_ast_check(prssr);                 /* Yes, kick it */
+               thread_lock(thread);
+               thread_ast_set(act, AST_BSD);
+               processor = thread->last_processor;
+               if (    processor != PROCESSOR_NULL                                             &&
+                               processor->state == PROCESSOR_RUNNING                   &&
+                               processor->cpu_data->active_thread == thread    )
+                       cause_ast_check(processor);
+               thread_unlock(thread);
        }
        
-       mp_enable_preemption();
+       splx(s);
 }
 
 void
-act_clr_apc(thread_act_t thr_act)
+act_set_apc(
+       thread_act_t    act)
 {
-       thread_ast_clear(thr_act, AST_APC);
+       spl_t                   s = splsched();
+       
+       if (act == current_act()) {
+               thread_ast_set(act, AST_APC);
+               ast_propagate(act->ast);
+       }
+       else {
+               thread_t                thread = act->thread;
+               processor_t             processor;
+
+               thread_lock(thread);
+               thread_ast_set(act, AST_APC);
+               processor = thread->last_processor;
+               if (    processor != PROCESSOR_NULL                                             &&
+                               processor->state == PROCESSOR_RUNNING                   &&
+                               processor->cpu_data->active_thread == thread    )
+                       cause_ast_check(processor);
+               thread_unlock(thread);
+       }
+       
+       splx(s);
 }
 
 void
@@ -2262,13 +1854,6 @@ act_ulock_release_all(thread_act_t thr_act)
  * Provide routines (for export to other components) of things that
  * are implemented as macros insternally.
  */
-#undef current_act
-thread_act_t
-current_act(void)
-{
-       return(current_act_fast());
-}
-
 thread_act_t
 thread_self(void)
 {
@@ -2302,4 +1887,3 @@ act_deallocate(
 {
        act_deallocate_fast(thr_act);
 }
-