- splx(spl);
-}
-
-/*
- * install_special_handler_locked
- * Do the work of installing the special_handler.
- *
- * Already locked: RPC-related locks for thr_act, plus the
- * scheduling lock (thread_lock()) of the associated thread.
- */
-void
-install_special_handler_locked(
- thread_act_t thr_act)
-{
- 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) {
- /*
- * 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);
- }
- }
- 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;
-
-kern_return_t
-thread_apc_set(
- thread_act_t thr_act,
- thread_apc_handler_t apc)
-{
- assert(apc == bsd_ast);
- thread_ast_set(thr_act, AST_BSD);
- if (thr_act == current_act())
- ast_propagate(thr_act->ast);
- return KERN_SUCCESS;
-}
-
-kern_return_t
-thread_apc_clear(
- thread_act_t thr_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);
- }
- }
-
- return KERN_SUCCESS;
-}
-
-/*
- * Activation control support routines internal to this file:
- */
-
-/*
- * act_execute_returnhandlers() - does just what the name says
- *
- * 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)
-{
- spl_t s;
- thread_t thread;
- thread_act_t thr_act = current_act();
-
-#if MACH_ASSERT
- if (watchacts & WA_ACT_HDLR)
- printf("execute_rtn_hdlrs: thr_act=%x\n", thr_act);
-#endif /* MACH_ASSERT */
-
- s = splsched();
- act_clr_apc(thr_act);