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