]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/thread_act.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / osfmk / kern / thread_act.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_FREE_COPYRIGHT@
30 */
31/*
32 * Copyright (c) 1993 The University of Utah and
33 * the Center for Software Science (CSS). All rights reserved.
34 *
35 * Permission to use, copy, modify and distribute this software and its
36 * documentation is hereby granted, provided that both the copyright
37 * notice and this permission notice appear in all copies of the
38 * software, derivative works or modified versions, and any portions
39 * thereof, and that both notices appear in supporting documentation.
40 *
41 * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
42 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
43 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
44 *
45 * CSS requests users of this software to return to css-dist@cs.utah.edu any
46 * improvements that they make and grant CSS redistribution rights.
47 *
48 * Author: Bryan Ford, University of Utah CSS
49 *
91447636 50 * Thread management routines
1c79356b 51 */
91447636 52#include <mach/mach_types.h>
1c79356b
A
53#include <mach/kern_return.h>
54#include <mach/alert.h>
91447636
A
55#include <mach_prof.h>
56#include <mach/rpc.h>
57#include <mach/thread_act_server.h>
58
59#include <kern/kern_types.h>
60#include <kern/ast.h>
1c79356b
A
61#include <kern/mach_param.h>
62#include <kern/zalloc.h>
63#include <kern/thread.h>
1c79356b 64#include <kern/task.h>
1c79356b
A
65#include <kern/sched_prim.h>
66#include <kern/misc_protos.h>
67#include <kern/assert.h>
68#include <kern/exception.h>
69#include <kern/ipc_mig.h>
70#include <kern/ipc_tt.h>
71#include <kern/profile.h>
72#include <kern/machine.h>
73#include <kern/spl.h>
74#include <kern/syscall_subr.h>
75#include <kern/sync_lock.h>
0b4e3aa0 76#include <kern/processor.h>
91447636 77#include <kern/timer.h>
1c79356b
A
78#include <mach_prof.h>
79#include <mach/rpc.h>
80
91447636
A
81void act_abort(thread_t);
82void act_set_apc(thread_t);
83void install_special_handler_locked(thread_t);
84void special_handler_continue(void);
1c79356b
A
85
86/*
87 * Internal routine to terminate a thread.
9bccf70c 88 * Sometimes called with task already locked.
1c79356b
A
89 */
90kern_return_t
91thread_terminate_internal(
91447636 92 thread_t thread)
1c79356b 93{
91447636 94 kern_return_t result = KERN_SUCCESS;
1c79356b 95
91447636 96 thread_mtx_lock(thread);
1c79356b 97
91447636
A
98 if (thread->active) {
99 thread->active = FALSE;
1c79356b 100
91447636 101 act_abort(thread);
e7c99d92 102
91447636
A
103 if (thread->started)
104 clear_wait(thread, THREAD_INTERRUPTED);
105 else {
106 clear_wait(thread, THREAD_AWAKENED);
107 thread->started = TRUE;
108 }
1c79356b 109 }
91447636
A
110 else
111 result = KERN_TERMINATED;
1c79356b 112
91447636
A
113 thread_mtx_unlock(thread);
114
115 if (thread != current_thread() && result == KERN_SUCCESS)
116 thread_wait(thread);
9bccf70c
A
117
118 return (result);
1c79356b
A
119}
120
121/*
9bccf70c 122 * Terminate a thread.
1c79356b
A
123 */
124kern_return_t
125thread_terminate(
91447636 126 thread_t thread)
1c79356b 127{
9bccf70c 128 kern_return_t result;
1c79356b 129
91447636 130 if (thread == THREAD_NULL)
9bccf70c 131 return (KERN_INVALID_ARGUMENT);
1c79356b 132
91447636
A
133 if ( thread->task == kernel_task &&
134 thread != current_thread() )
9bccf70c 135 return (KERN_FAILURE);
1c79356b 136
91447636 137 result = thread_terminate_internal(thread);
1c79356b
A
138
139 /*
140 * If a kernel thread is terminating itself, force an AST here.
141 * Kernel threads don't normally pass through the AST checking
142 * code - and all threads finish their own termination in the
143 * special handler APC.
144 */
91447636 145 if (thread->task == kernel_task) {
55e303ae 146 ml_set_interrupts_enabled(FALSE);
55e303ae 147 ast_taken(AST_APC, TRUE);
9bccf70c
A
148 panic("thread_terminate");
149 }
1c79356b 150
9bccf70c 151 return (result);
1c79356b
A
152}
153
154/*
9bccf70c
A
155 * Suspend execution of the specified thread.
156 * This is a recursive-style suspension of the thread, a count of
157 * suspends is maintained.
1c79356b 158 *
91447636 159 * Called with thread mutex held.
1c79356b
A
160 */
161void
162thread_hold(
91447636 163 register thread_t thread)
1c79356b 164{
91447636
A
165 if (thread->suspend_count++ == 0) {
166 install_special_handler(thread);
167 if (thread->started)
168 thread_wakeup_one(&thread->suspend_count);
1c79356b
A
169 }
170}
171
172/*
91447636 173 * Decrement internal suspension count, setting thread
1c79356b
A
174 * runnable when count falls to zero.
175 *
91447636 176 * Called with thread mutex held.
1c79356b
A
177 */
178void
179thread_release(
91447636 180 register thread_t thread)
1c79356b 181{
91447636
A
182 if ( thread->suspend_count > 0 &&
183 --thread->suspend_count == 0 ) {
184 if (thread->started)
185 thread_wakeup_one(&thread->suspend_count);
186 else {
9bccf70c 187 clear_wait(thread, THREAD_AWAKENED);
91447636 188 thread->started = TRUE;
9bccf70c 189 }
9bccf70c 190 }
1c79356b
A
191}
192
193kern_return_t
194thread_suspend(
91447636 195 register thread_t thread)
1c79356b 196{
91447636
A
197 thread_t self = current_thread();
198 kern_return_t result = KERN_SUCCESS;
1c79356b 199
91447636 200 if (thread == THREAD_NULL || thread->task == kernel_task)
9bccf70c
A
201 return (KERN_INVALID_ARGUMENT);
202
91447636 203 thread_mtx_lock(thread);
9bccf70c 204
91447636
A
205 if (thread->active) {
206 if ( thread->user_stop_count++ == 0 &&
207 thread->suspend_count++ == 0 ) {
208 install_special_handler(thread);
209 if (thread != self)
210 thread_wakeup_one(&thread->suspend_count);
1c79356b
A
211 }
212 }
9bccf70c 213 else
91447636
A
214 result = KERN_TERMINATED;
215
216 thread_mtx_unlock(thread);
217
218 if (thread != self && result == KERN_SUCCESS)
219 thread_wait(thread);
9bccf70c 220
91447636 221 return (result);
1c79356b
A
222}
223
224kern_return_t
225thread_resume(
91447636 226 register thread_t thread)
1c79356b 227{
91447636 228 kern_return_t result = KERN_SUCCESS;
1c79356b 229
91447636 230 if (thread == THREAD_NULL || thread->task == kernel_task)
9bccf70c 231 return (KERN_INVALID_ARGUMENT);
1c79356b 232
91447636 233 thread_mtx_lock(thread);
9bccf70c 234
91447636
A
235 if (thread->active) {
236 if (thread->user_stop_count > 0) {
237 if ( --thread->user_stop_count == 0 &&
238 --thread->suspend_count == 0 ) {
239 if (thread->started)
240 thread_wakeup_one(&thread->suspend_count);
241 else {
9bccf70c 242 clear_wait(thread, THREAD_AWAKENED);
91447636 243 thread->started = TRUE;
9bccf70c 244 }
1c79356b
A
245 }
246 }
247 else
9bccf70c 248 result = KERN_FAILURE;
1c79356b
A
249 }
250 else
9bccf70c
A
251 result = KERN_TERMINATED;
252
91447636 253 thread_mtx_unlock(thread);
9bccf70c
A
254
255 return (result);
1c79356b
A
256}
257
1c79356b
A
258/*
259 * thread_depress_abort:
260 *
261 * Prematurely abort priority depression if there is one.
262 */
263kern_return_t
264thread_depress_abort(
91447636 265 register thread_t thread)
1c79356b 266{
91447636 267 kern_return_t result;
1c79356b 268
91447636 269 if (thread == THREAD_NULL)
1c79356b
A
270 return (KERN_INVALID_ARGUMENT);
271
91447636 272 thread_mtx_lock(thread);
1c79356b 273
91447636
A
274 if (thread->active)
275 result = thread_depress_abort_internal(thread);
276 else
277 result = KERN_TERMINATED;
1c79356b 278
91447636 279 thread_mtx_unlock(thread);
1c79356b
A
280
281 return (result);
282}
283
284
285/*
9bccf70c 286 * Indicate that the activation should run its
91447636 287 * special handler to detect a condition.
9bccf70c 288 *
91447636 289 * Called with thread mutex held.
1c79356b 290 */
91447636 291void
9bccf70c 292act_abort(
91447636 293 thread_t thread)
1c79356b 294{
9bccf70c 295 spl_t s = splsched();
1c79356b 296
9bccf70c 297 thread_lock(thread);
91447636 298
9bccf70c
A
299 if (!(thread->state & TH_ABORT)) {
300 thread->state |= TH_ABORT;
91447636 301 install_special_handler_locked(thread);
1c79356b 302 }
91447636
A
303 else
304 thread->state &= ~TH_ABORT_SAFELY;
305
9bccf70c
A
306 thread_unlock(thread);
307 splx(s);
1c79356b
A
308}
309
310kern_return_t
311thread_abort(
91447636 312 register thread_t thread)
1c79356b 313{
91447636 314 kern_return_t result = KERN_SUCCESS;
1c79356b 315
91447636 316 if (thread == THREAD_NULL)
1c79356b 317 return (KERN_INVALID_ARGUMENT);
9bccf70c 318
91447636 319 thread_mtx_lock(thread);
9bccf70c 320
91447636
A
321 if (thread->active) {
322 act_abort(thread);
323 clear_wait(thread, THREAD_INTERRUPTED);
1c79356b 324 }
91447636
A
325 else
326 result = KERN_TERMINATED;
1c79356b 327
91447636 328 thread_mtx_unlock(thread);
9bccf70c
A
329
330 return (result);
1c79356b
A
331}
332
333kern_return_t
334thread_abort_safely(
91447636 335 thread_t thread)
1c79356b 336{
91447636 337 kern_return_t result = KERN_SUCCESS;
1c79356b 338
91447636 339 if (thread == THREAD_NULL)
9bccf70c 340 return (KERN_INVALID_ARGUMENT);
1c79356b 341
91447636 342 thread_mtx_lock(thread);
9bccf70c 343
91447636
A
344 if (thread->active) {
345 spl_t s = splsched();
9bccf70c 346
91447636
A
347 thread_lock(thread);
348 if (!thread->at_safe_point ||
349 clear_wait_internal(thread, THREAD_INTERRUPTED) != KERN_SUCCESS) {
350 if (!(thread->state & TH_ABORT)) {
351 thread->state |= (TH_ABORT|TH_ABORT_SAFELY);
352 install_special_handler_locked(thread);
353 }
9bccf70c 354 }
91447636
A
355 thread_unlock(thread);
356 splx(s);
1c79356b 357 }
91447636
A
358 else
359 result = KERN_TERMINATED;
9bccf70c 360
91447636 361 thread_mtx_unlock(thread);
9bccf70c 362
91447636 363 return (result);
1c79356b
A
364}
365
366/*** backward compatibility hacks ***/
367#include <mach/thread_info.h>
368#include <mach/thread_special_ports.h>
369#include <ipc/ipc_port.h>
1c79356b
A
370
371kern_return_t
372thread_info(
91447636 373 thread_t thread,
1c79356b
A
374 thread_flavor_t flavor,
375 thread_info_t thread_info_out,
376 mach_msg_type_number_t *thread_info_count)
377{
1c79356b
A
378 kern_return_t result;
379
91447636 380 if (thread == THREAD_NULL)
1c79356b
A
381 return (KERN_INVALID_ARGUMENT);
382
91447636 383 thread_mtx_lock(thread);
1c79356b 384
91447636
A
385 if (thread->active)
386 result = thread_info_internal(
387 thread, flavor, thread_info_out, thread_info_count);
388 else
389 result = KERN_TERMINATED;
1c79356b 390
91447636 391 thread_mtx_unlock(thread);
1c79356b
A
392
393 return (result);
394}
395
1c79356b 396kern_return_t
91447636
A
397thread_get_state(
398 register thread_t thread,
399 int flavor,
400 thread_state_t state, /* pointer to OUT array */
401 mach_msg_type_number_t *state_count) /*IN/OUT*/
1c79356b 402{
91447636 403 kern_return_t result = KERN_SUCCESS;
1c79356b 404
91447636
A
405 if (thread == THREAD_NULL)
406 return (KERN_INVALID_ARGUMENT);
1c79356b 407
91447636 408 thread_mtx_lock(thread);
1c79356b 409
91447636
A
410 if (thread->active) {
411 if (thread != current_thread()) {
412 thread_hold(thread);
1c79356b 413
91447636 414 thread_mtx_unlock(thread);
1c79356b 415
91447636
A
416 if (thread_stop(thread)) {
417 thread_mtx_lock(thread);
418 result = machine_thread_get_state(
419 thread, flavor, state, state_count);
420 thread_unstop(thread);
421 }
422 else {
423 thread_mtx_lock(thread);
424 result = KERN_ABORTED;
425 }
1c79356b 426
91447636
A
427 thread_release(thread);
428 }
429 else
430 result = machine_thread_get_state(
431 thread, flavor, state, state_count);
1c79356b 432 }
91447636
A
433 else
434 result = KERN_TERMINATED;
1c79356b 435
91447636 436 thread_mtx_unlock(thread);
1c79356b 437
91447636 438 return (result);
1c79356b
A
439}
440
441/*
91447636
A
442 * Change thread's machine-dependent state. Called with nothing
443 * locked. Returns same way.
1c79356b
A
444 */
445kern_return_t
91447636
A
446thread_set_state(
447 register thread_t thread,
9bccf70c 448 int flavor,
91447636
A
449 thread_state_t state,
450 mach_msg_type_number_t state_count)
1c79356b 451{
9bccf70c 452 kern_return_t result = KERN_SUCCESS;
1c79356b 453
91447636 454 if (thread == THREAD_NULL)
1c79356b
A
455 return (KERN_INVALID_ARGUMENT);
456
91447636 457 thread_mtx_lock(thread);
9bccf70c 458
91447636
A
459 if (thread->active) {
460 if (thread != current_thread()) {
461 thread_hold(thread);
1c79356b 462
91447636 463 thread_mtx_unlock(thread);
9bccf70c 464
91447636
A
465 if (thread_stop(thread)) {
466 thread_mtx_lock(thread);
467 result = machine_thread_set_state(
468 thread, flavor, state, state_count);
469 thread_unstop(thread);
470 }
471 else {
472 thread_mtx_lock(thread);
473 result = KERN_ABORTED;
474 }
9bccf70c 475
91447636 476 thread_release(thread);
9bccf70c 477 }
91447636
A
478 else
479 result = machine_thread_set_state(
480 thread, flavor, state, state_count);
1c79356b 481 }
91447636
A
482 else
483 result = KERN_TERMINATED;
1c79356b 484
91447636 485 thread_mtx_unlock(thread);
9bccf70c
A
486
487 return (result);
1c79356b 488}
91447636
A
489
490
1c79356b 491/*
91447636
A
492 * Kernel-internal "thread" interfaces used outside this file:
493 */
494
495/* Initialize (or re-initialize) a thread state. Called from execve
496 * with nothing locked, returns same way.
1c79356b
A
497 */
498kern_return_t
91447636
A
499thread_state_initialize(
500 register thread_t thread)
1c79356b 501{
9bccf70c 502 kern_return_t result = KERN_SUCCESS;
1c79356b 503
91447636 504 if (thread == THREAD_NULL)
1c79356b 505 return (KERN_INVALID_ARGUMENT);
1c79356b 506
91447636 507 thread_mtx_lock(thread);
9bccf70c 508
91447636
A
509 if (thread->active) {
510 if (thread != current_thread()) {
511 thread_hold(thread);
9bccf70c 512
91447636 513 thread_mtx_unlock(thread);
9bccf70c 514
91447636
A
515 if (thread_stop(thread)) {
516 thread_mtx_lock(thread);
517 result = machine_thread_state_initialize( thread );
518 thread_unstop(thread);
519 }
520 else {
521 thread_mtx_lock(thread);
522 result = KERN_ABORTED;
523 }
9bccf70c 524
91447636 525 thread_release(thread);
9bccf70c 526 }
91447636
A
527 else
528 result = machine_thread_state_initialize( thread );
1c79356b 529 }
91447636
A
530 else
531 result = KERN_TERMINATED;
9bccf70c 532
91447636 533 thread_mtx_unlock(thread);
9bccf70c
A
534
535 return (result);
1c79356b
A
536}
537
1c79356b
A
538
539kern_return_t
540thread_dup(
91447636 541 register thread_t target)
1c79356b 542{
91447636 543 thread_t self = current_thread();
9bccf70c 544 kern_return_t result = KERN_SUCCESS;
1c79356b 545
91447636 546 if (target == THREAD_NULL || target == self)
1c79356b
A
547 return (KERN_INVALID_ARGUMENT);
548
91447636 549 thread_mtx_lock(target);
9bccf70c 550
91447636
A
551 if (target->active) {
552 thread_hold(target);
9bccf70c 553
91447636 554 thread_mtx_unlock(target);
9bccf70c 555
91447636
A
556 if (thread_stop(target)) {
557 thread_mtx_lock(target);
558 result = machine_thread_dup(self, target);
559 thread_unstop(target);
560 }
561 else {
562 thread_mtx_lock(target);
9bccf70c 563 result = KERN_ABORTED;
9bccf70c
A
564 }
565
91447636 566 thread_release(target);
1c79356b 567 }
91447636
A
568 else
569 result = KERN_TERMINATED;
9bccf70c 570
91447636 571 thread_mtx_unlock(target);
9bccf70c
A
572
573 return (result);
1c79356b
A
574}
575
576
577/*
578 * thread_setstatus:
579 *
580 * Set the status of the specified thread.
581 * Called with (and returns with) no locks held.
582 */
583kern_return_t
584thread_setstatus(
91447636 585 register thread_t thread,
9bccf70c
A
586 int flavor,
587 thread_state_t tstate,
1c79356b
A
588 mach_msg_type_number_t count)
589{
9bccf70c 590
91447636 591 return (thread_set_state(thread, flavor, tstate, count));
1c79356b
A
592}
593
594/*
595 * thread_getstatus:
596 *
597 * Get the status of the specified thread.
598 */
599kern_return_t
600thread_getstatus(
91447636 601 register thread_t thread,
9bccf70c
A
602 int flavor,
603 thread_state_t tstate,
1c79356b
A
604 mach_msg_type_number_t *count)
605{
91447636 606 return (thread_get_state(thread, flavor, tstate, count));
1c79356b
A
607}
608
609/*
91447636 610 * install_special_handler:
1c79356b 611 *
1c79356b
A
612 * Install the special returnhandler that handles suspension and
613 * termination, if it hasn't been installed already.
614 *
91447636 615 * Called with the thread mutex held.
1c79356b
A
616 */
617void
618install_special_handler(
91447636 619 thread_t thread)
1c79356b 620{
91447636 621 spl_t s = splsched();
1c79356b 622
e7c99d92 623 thread_lock(thread);
91447636 624 install_special_handler_locked(thread);
e7c99d92 625 thread_unlock(thread);
91447636 626 splx(s);
1c79356b
A
627}
628
629/*
91447636
A
630 * install_special_handler_locked:
631 *
1c79356b
A
632 * Do the work of installing the special_handler.
633 *
91447636 634 * Called with the thread mutex and scheduling lock held.
1c79356b
A
635 */
636void
637install_special_handler_locked(
91447636 638 thread_t thread)
1c79356b
A
639{
640 ReturnHandler **rh;
1c79356b
A
641
642 /* The work handler must always be the last ReturnHandler on the list,
643 because it can do tricky things like detach the thr_act. */
91447636 644 for (rh = &thread->handlers; *rh; rh = &(*rh)->next)
9bccf70c 645 continue;
1c79356b 646
91447636
A
647 if (rh != &thread->special_handler.next)
648 *rh = &thread->special_handler;
649
650 /*
651 * Temporarily undepress, so target has
652 * a chance to do locking required to
653 * block itself in special_handler().
654 */
655 if (thread->sched_mode & TH_MODE_ISDEPRESSED)
656 compute_priority(thread, TRUE);
657
658 thread_ast_set(thread, AST_APC);
659
660 if (thread == current_thread())
661 ast_propagate(thread->ast);
9bccf70c
A
662 else {
663 processor_t processor = thread->last_processor;
664
55e303ae
A
665 if ( processor != PROCESSOR_NULL &&
666 processor->state == PROCESSOR_RUNNING &&
667 processor->active_thread == thread )
9bccf70c
A
668 cause_ast_check(processor);
669 }
670}
1c79356b 671
1c79356b
A
672/*
673 * Activation control support routines internal to this file:
674 */
675
9bccf70c
A
676void
677act_execute_returnhandlers(void)
1c79356b 678{
91447636 679 thread_t thread = current_thread();
1c79356b 680
91447636 681 thread_ast_clear(thread, AST_APC);
1c79356b 682 spllo();
1c79356b 683
9bccf70c
A
684 for (;;) {
685 ReturnHandler *rh;
91447636
A
686
687 thread_mtx_lock(thread);
9bccf70c 688
1c79356b
A
689 (void)splsched();
690 thread_lock(thread);
91447636
A
691
692 rh = thread->handlers;
693 if (rh != NULL) {
694 thread->handlers = rh->next;
695
1c79356b 696 thread_unlock(thread);
9bccf70c 697 spllo();
1c79356b 698
91447636
A
699 thread_mtx_unlock(thread);
700
701 /* Execute it */
702 (*rh->handler)(rh, thread);
703 }
704 else
705 break;
1c79356b 706 }
91447636
A
707
708 thread_unlock(thread);
709 spllo();
710
711 thread_mtx_unlock(thread);
1c79356b
A
712}
713
714/*
715 * special_handler_continue
716 *
717 * Continuation routine for the special handler blocks. It checks
718 * to see whether there has been any new suspensions. If so, it
719 * installs the special handler again. Otherwise, it checks to see
720 * if the current depression needs to be re-instated (it may have
721 * been temporarily removed in order to get to this point in a hurry).
722 */
723void
724special_handler_continue(void)
725{
91447636
A
726 thread_t thread = current_thread();
727
728 thread_mtx_lock(thread);
1c79356b 729
91447636
A
730 if (thread->suspend_count > 0)
731 install_special_handler(thread);
1c79356b 732 else {
9bccf70c
A
733 spl_t s = splsched();
734
1c79356b 735 thread_lock(thread);
9bccf70c
A
736 if (thread->sched_mode & TH_MODE_ISDEPRESSED) {
737 processor_t myprocessor = thread->last_processor;
738
739 thread->sched_pri = DEPRESSPRI;
740 myprocessor->current_pri = thread->sched_pri;
741 thread->sched_mode &= ~TH_MODE_PREEMPT;
1c79356b
A
742 }
743 thread_unlock(thread);
744 splx(s);
745 }
9bccf70c 746
91447636
A
747 thread_mtx_unlock(thread);
748
1c79356b 749 thread_exception_return();
9bccf70c 750 /*NOTREACHED*/
1c79356b
A
751}
752
753/*
754 * special_handler - handles suspension, termination. Called
755 * with nothing locked. Returns (if it returns) the same way.
756 */
757void
758special_handler(
91447636
A
759 __unused ReturnHandler *rh,
760 thread_t thread)
1c79356b 761{
91447636 762 spl_t s;
1c79356b 763
91447636 764 thread_mtx_lock(thread);
1c79356b
A
765
766 s = splsched();
1c79356b 767 thread_lock(thread);
9bccf70c 768 thread->state &= ~(TH_ABORT|TH_ABORT_SAFELY); /* clear any aborts */
1c79356b
A
769 thread_unlock(thread);
770 splx(s);
771
1c79356b
A
772 /*
773 * If we're suspended, go to sleep and wait for someone to wake us up.
774 */
91447636
A
775 if (thread->active) {
776 if (thread->suspend_count > 0) {
777 if (thread->handlers == NULL) {
778 assert_wait(&thread->suspend_count, THREAD_ABORTSAFE);
779 thread_mtx_unlock(thread);
780 thread_block((thread_continue_t)special_handler_continue);
781 /*NOTREACHED*/
782 }
9bccf70c 783
91447636 784 thread_mtx_unlock(thread);
9bccf70c 785
91447636
A
786 special_handler_continue();
787 /*NOTREACHED*/
9bccf70c 788 }
1c79356b 789 }
91447636
A
790 else {
791 thread_mtx_unlock(thread);
1c79356b 792
91447636
A
793 thread_terminate_self();
794 /*NOTREACHED*/
795 }
1c79356b 796
91447636 797 thread_mtx_unlock(thread);
1c79356b
A
798}
799
800kern_return_t
91447636
A
801act_set_state(
802 thread_t thread,
803 int flavor,
804 thread_state_t state,
805 mach_msg_type_number_t count)
1c79356b 806{
91447636
A
807 if (thread == current_thread())
808 return (KERN_INVALID_ARGUMENT);
1c79356b 809
91447636 810 return (thread_set_state(thread, flavor, state, count));
1c79356b
A
811
812}
813
814kern_return_t
91447636
A
815act_get_state(
816 thread_t thread,
817 int flavor,
818 thread_state_t state,
819 mach_msg_type_number_t *count)
1c79356b 820{
91447636
A
821 if (thread == current_thread())
822 return (KERN_INVALID_ARGUMENT);
1c79356b 823
91447636 824 return (thread_get_state(thread, flavor, state, count));
1c79356b
A
825}
826
1c79356b 827void
9bccf70c 828act_set_astbsd(
91447636 829 thread_t thread)
1c79356b 830{
91447636 831 spl_t s = splsched();
0b4e3aa0 832
91447636
A
833 if (thread == current_thread()) {
834 thread_ast_set(thread, AST_BSD);
835 ast_propagate(thread->ast);
1c79356b 836 }
9bccf70c 837 else {
9bccf70c 838 processor_t processor;
0b4e3aa0 839
9bccf70c 840 thread_lock(thread);
91447636 841 thread_ast_set(thread, AST_BSD);
9bccf70c 842 processor = thread->last_processor;
55e303ae
A
843 if ( processor != PROCESSOR_NULL &&
844 processor->state == PROCESSOR_RUNNING &&
845 processor->active_thread == thread )
9bccf70c
A
846 cause_ast_check(processor);
847 thread_unlock(thread);
0b4e3aa0
A
848 }
849
9bccf70c 850 splx(s);
1c79356b
A
851}
852
853void
9bccf70c 854act_set_apc(
91447636 855 thread_t thread)
1c79356b 856{
91447636 857 spl_t s = splsched();
9bccf70c 858
91447636
A
859 if (thread == current_thread()) {
860 thread_ast_set(thread, AST_APC);
861 ast_propagate(thread->ast);
9bccf70c
A
862 }
863 else {
9bccf70c
A
864 processor_t processor;
865
866 thread_lock(thread);
91447636 867 thread_ast_set(thread, AST_APC);
9bccf70c 868 processor = thread->last_processor;
55e303ae
A
869 if ( processor != PROCESSOR_NULL &&
870 processor->state == PROCESSOR_RUNNING &&
871 processor->active_thread == thread )
9bccf70c
A
872 cause_ast_check(processor);
873 thread_unlock(thread);
874 }
875
876 splx(s);
1c79356b 877}