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