]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/thread_act.c
xnu-1699.24.8.tar.gz
[apple/xnu.git] / osfmk / kern / thread_act.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 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/rpc.h>
56#include <mach/thread_act_server.h>
57
58#include <kern/kern_types.h>
59#include <kern/ast.h>
1c79356b
A
60#include <kern/mach_param.h>
61#include <kern/zalloc.h>
6d2010ae 62#include <kern/extmod_statistics.h>
1c79356b 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>
1c79356b
A
71#include <kern/machine.h>
72#include <kern/spl.h>
73#include <kern/syscall_subr.h>
74#include <kern/sync_lock.h>
0b4e3aa0 75#include <kern/processor.h>
91447636 76#include <kern/timer.h>
2d21ac55
A
77#include <kern/affinity.h>
78
1c79356b
A
79#include <mach/rpc.h>
80
91447636 81void act_abort(thread_t);
91447636
A
82void install_special_handler_locked(thread_t);
83void special_handler_continue(void);
1c79356b 84
2d21ac55
A
85/*
86 * Internal routine to mark a thread as started.
87 * Always called with the thread locked.
88 *
b0d623f7 89 * Note: function intentionally declared with the noinline attribute to
2d21ac55
A
90 * prevent multiple declaration of probe symbols in this file; we would
91 * prefer "#pragma noinline", but gcc does not support it.
b0d623f7
A
92 * PR-6385749 -- the lwp-start probe should fire from within the context
93 * of the newly created thread. Commented out for now, in case we
94 * turn it into a dead code probe.
2d21ac55
A
95 */
96void
97thread_start_internal(
98 thread_t thread)
99{
100 clear_wait(thread, THREAD_AWAKENED);
101 thread->started = TRUE;
b0d623f7 102 // DTRACE_PROC1(lwp__start, thread_t, thread);
2d21ac55
A
103}
104
1c79356b
A
105/*
106 * Internal routine to terminate a thread.
9bccf70c 107 * Sometimes called with task already locked.
1c79356b
A
108 */
109kern_return_t
110thread_terminate_internal(
91447636 111 thread_t thread)
1c79356b 112{
91447636 113 kern_return_t result = KERN_SUCCESS;
1c79356b 114
91447636 115 thread_mtx_lock(thread);
1c79356b 116
91447636
A
117 if (thread->active) {
118 thread->active = FALSE;
1c79356b 119
91447636 120 act_abort(thread);
e7c99d92 121
91447636
A
122 if (thread->started)
123 clear_wait(thread, THREAD_INTERRUPTED);
124 else {
2d21ac55 125 thread_start_internal(thread);
91447636 126 }
1c79356b 127 }
91447636
A
128 else
129 result = KERN_TERMINATED;
1c79356b 130
2d21ac55
A
131 if (thread->affinity_set != NULL)
132 thread_affinity_terminate(thread);
133
91447636
A
134 thread_mtx_unlock(thread);
135
136 if (thread != current_thread() && result == KERN_SUCCESS)
137 thread_wait(thread);
9bccf70c
A
138
139 return (result);
1c79356b
A
140}
141
142/*
9bccf70c 143 * Terminate a thread.
1c79356b
A
144 */
145kern_return_t
146thread_terminate(
91447636 147 thread_t thread)
1c79356b 148{
9bccf70c 149 kern_return_t result;
1c79356b 150
91447636 151 if (thread == THREAD_NULL)
9bccf70c 152 return (KERN_INVALID_ARGUMENT);
1c79356b 153
91447636
A
154 if ( thread->task == kernel_task &&
155 thread != current_thread() )
9bccf70c 156 return (KERN_FAILURE);
1c79356b 157
91447636 158 result = thread_terminate_internal(thread);
1c79356b
A
159
160 /*
161 * If a kernel thread is terminating itself, force an AST here.
162 * Kernel threads don't normally pass through the AST checking
163 * code - and all threads finish their own termination in the
164 * special handler APC.
165 */
91447636 166 if (thread->task == kernel_task) {
55e303ae 167 ml_set_interrupts_enabled(FALSE);
55e303ae 168 ast_taken(AST_APC, TRUE);
9bccf70c
A
169 panic("thread_terminate");
170 }
1c79356b 171
9bccf70c 172 return (result);
1c79356b
A
173}
174
175/*
9bccf70c
A
176 * Suspend execution of the specified thread.
177 * This is a recursive-style suspension of the thread, a count of
178 * suspends is maintained.
1c79356b 179 *
91447636 180 * Called with thread mutex held.
1c79356b
A
181 */
182void
183thread_hold(
91447636 184 register thread_t thread)
1c79356b 185{
91447636
A
186 if (thread->suspend_count++ == 0) {
187 install_special_handler(thread);
188 if (thread->started)
189 thread_wakeup_one(&thread->suspend_count);
1c79356b
A
190 }
191}
192
193/*
91447636 194 * Decrement internal suspension count, setting thread
1c79356b
A
195 * runnable when count falls to zero.
196 *
91447636 197 * Called with thread mutex held.
1c79356b
A
198 */
199void
200thread_release(
91447636 201 register thread_t thread)
1c79356b 202{
91447636
A
203 if ( thread->suspend_count > 0 &&
204 --thread->suspend_count == 0 ) {
205 if (thread->started)
206 thread_wakeup_one(&thread->suspend_count);
207 else {
2d21ac55 208 thread_start_internal(thread);
9bccf70c 209 }
9bccf70c 210 }
1c79356b
A
211}
212
213kern_return_t
214thread_suspend(
91447636 215 register thread_t thread)
1c79356b 216{
91447636
A
217 thread_t self = current_thread();
218 kern_return_t result = KERN_SUCCESS;
1c79356b 219
91447636 220 if (thread == THREAD_NULL || thread->task == kernel_task)
9bccf70c
A
221 return (KERN_INVALID_ARGUMENT);
222
91447636 223 thread_mtx_lock(thread);
9bccf70c 224
91447636
A
225 if (thread->active) {
226 if ( thread->user_stop_count++ == 0 &&
227 thread->suspend_count++ == 0 ) {
228 install_special_handler(thread);
229 if (thread != self)
230 thread_wakeup_one(&thread->suspend_count);
1c79356b
A
231 }
232 }
9bccf70c 233 else
91447636
A
234 result = KERN_TERMINATED;
235
236 thread_mtx_unlock(thread);
237
238 if (thread != self && result == KERN_SUCCESS)
239 thread_wait(thread);
9bccf70c 240
91447636 241 return (result);
1c79356b
A
242}
243
244kern_return_t
245thread_resume(
91447636 246 register thread_t thread)
1c79356b 247{
91447636 248 kern_return_t result = KERN_SUCCESS;
1c79356b 249
91447636 250 if (thread == THREAD_NULL || thread->task == kernel_task)
9bccf70c 251 return (KERN_INVALID_ARGUMENT);
1c79356b 252
91447636 253 thread_mtx_lock(thread);
9bccf70c 254
91447636
A
255 if (thread->active) {
256 if (thread->user_stop_count > 0) {
257 if ( --thread->user_stop_count == 0 &&
258 --thread->suspend_count == 0 ) {
259 if (thread->started)
260 thread_wakeup_one(&thread->suspend_count);
261 else {
2d21ac55 262 thread_start_internal(thread);
9bccf70c 263 }
1c79356b
A
264 }
265 }
266 else
9bccf70c 267 result = KERN_FAILURE;
1c79356b
A
268 }
269 else
9bccf70c
A
270 result = KERN_TERMINATED;
271
91447636 272 thread_mtx_unlock(thread);
9bccf70c
A
273
274 return (result);
1c79356b
A
275}
276
1c79356b
A
277/*
278 * thread_depress_abort:
279 *
280 * Prematurely abort priority depression if there is one.
281 */
282kern_return_t
283thread_depress_abort(
91447636 284 register thread_t thread)
1c79356b 285{
91447636 286 kern_return_t result;
1c79356b 287
91447636 288 if (thread == THREAD_NULL)
1c79356b
A
289 return (KERN_INVALID_ARGUMENT);
290
91447636 291 thread_mtx_lock(thread);
1c79356b 292
91447636
A
293 if (thread->active)
294 result = thread_depress_abort_internal(thread);
295 else
296 result = KERN_TERMINATED;
1c79356b 297
91447636 298 thread_mtx_unlock(thread);
1c79356b
A
299
300 return (result);
301}
302
303
304/*
9bccf70c 305 * Indicate that the activation should run its
91447636 306 * special handler to detect a condition.
9bccf70c 307 *
91447636 308 * Called with thread mutex held.
1c79356b 309 */
91447636 310void
9bccf70c 311act_abort(
91447636 312 thread_t thread)
1c79356b 313{
9bccf70c 314 spl_t s = splsched();
1c79356b 315
9bccf70c 316 thread_lock(thread);
91447636 317
6d2010ae
A
318 if (!(thread->sched_flags & TH_SFLAG_ABORT)) {
319 thread->sched_flags |= TH_SFLAG_ABORT;
91447636 320 install_special_handler_locked(thread);
1c79356b 321 }
91447636 322 else
6d2010ae 323 thread->sched_flags &= ~TH_SFLAG_ABORTSAFELY;
91447636 324
9bccf70c
A
325 thread_unlock(thread);
326 splx(s);
1c79356b
A
327}
328
329kern_return_t
330thread_abort(
91447636 331 register thread_t thread)
1c79356b 332{
91447636 333 kern_return_t result = KERN_SUCCESS;
1c79356b 334
91447636 335 if (thread == THREAD_NULL)
1c79356b 336 return (KERN_INVALID_ARGUMENT);
9bccf70c 337
91447636 338 thread_mtx_lock(thread);
9bccf70c 339
91447636
A
340 if (thread->active) {
341 act_abort(thread);
342 clear_wait(thread, THREAD_INTERRUPTED);
1c79356b 343 }
91447636
A
344 else
345 result = KERN_TERMINATED;
1c79356b 346
91447636 347 thread_mtx_unlock(thread);
9bccf70c
A
348
349 return (result);
1c79356b
A
350}
351
352kern_return_t
353thread_abort_safely(
91447636 354 thread_t thread)
1c79356b 355{
91447636 356 kern_return_t result = KERN_SUCCESS;
1c79356b 357
91447636 358 if (thread == THREAD_NULL)
9bccf70c 359 return (KERN_INVALID_ARGUMENT);
1c79356b 360
91447636 361 thread_mtx_lock(thread);
9bccf70c 362
91447636
A
363 if (thread->active) {
364 spl_t s = splsched();
9bccf70c 365
91447636
A
366 thread_lock(thread);
367 if (!thread->at_safe_point ||
2d21ac55 368 clear_wait_internal(thread, THREAD_INTERRUPTED) != KERN_SUCCESS) {
6d2010ae
A
369 if (!(thread->sched_flags & TH_SFLAG_ABORT)) {
370 thread->sched_flags |= TH_SFLAG_ABORTED_MASK;
91447636
A
371 install_special_handler_locked(thread);
372 }
9bccf70c 373 }
91447636
A
374 thread_unlock(thread);
375 splx(s);
1c79356b 376 }
91447636
A
377 else
378 result = KERN_TERMINATED;
9bccf70c 379
91447636 380 thread_mtx_unlock(thread);
9bccf70c 381
91447636 382 return (result);
1c79356b
A
383}
384
385/*** backward compatibility hacks ***/
386#include <mach/thread_info.h>
387#include <mach/thread_special_ports.h>
388#include <ipc/ipc_port.h>
1c79356b
A
389
390kern_return_t
391thread_info(
91447636 392 thread_t thread,
1c79356b
A
393 thread_flavor_t flavor,
394 thread_info_t thread_info_out,
395 mach_msg_type_number_t *thread_info_count)
396{
1c79356b
A
397 kern_return_t result;
398
91447636 399 if (thread == THREAD_NULL)
1c79356b
A
400 return (KERN_INVALID_ARGUMENT);
401
91447636 402 thread_mtx_lock(thread);
1c79356b 403
91447636
A
404 if (thread->active)
405 result = thread_info_internal(
406 thread, flavor, thread_info_out, thread_info_count);
407 else
408 result = KERN_TERMINATED;
1c79356b 409
91447636 410 thread_mtx_unlock(thread);
1c79356b
A
411
412 return (result);
413}
414
1c79356b 415kern_return_t
91447636
A
416thread_get_state(
417 register thread_t thread,
418 int flavor,
419 thread_state_t state, /* pointer to OUT array */
420 mach_msg_type_number_t *state_count) /*IN/OUT*/
1c79356b 421{
91447636 422 kern_return_t result = KERN_SUCCESS;
1c79356b 423
91447636
A
424 if (thread == THREAD_NULL)
425 return (KERN_INVALID_ARGUMENT);
1c79356b 426
91447636 427 thread_mtx_lock(thread);
1c79356b 428
91447636
A
429 if (thread->active) {
430 if (thread != current_thread()) {
431 thread_hold(thread);
1c79356b 432
91447636 433 thread_mtx_unlock(thread);
1c79356b 434
91447636
A
435 if (thread_stop(thread)) {
436 thread_mtx_lock(thread);
437 result = machine_thread_get_state(
438 thread, flavor, state, state_count);
439 thread_unstop(thread);
440 }
441 else {
442 thread_mtx_lock(thread);
443 result = KERN_ABORTED;
444 }
1c79356b 445
91447636
A
446 thread_release(thread);
447 }
448 else
449 result = machine_thread_get_state(
450 thread, flavor, state, state_count);
1c79356b 451 }
91447636
A
452 else
453 result = KERN_TERMINATED;
1c79356b 454
91447636 455 thread_mtx_unlock(thread);
1c79356b 456
91447636 457 return (result);
1c79356b
A
458}
459
460/*
91447636
A
461 * Change thread's machine-dependent state. Called with nothing
462 * locked. Returns same way.
1c79356b 463 */
6d2010ae
A
464static kern_return_t
465thread_set_state_internal(
91447636 466 register thread_t thread,
9bccf70c 467 int flavor,
91447636 468 thread_state_t state,
6d2010ae
A
469 mach_msg_type_number_t state_count,
470 boolean_t from_user)
1c79356b 471{
9bccf70c 472 kern_return_t result = KERN_SUCCESS;
1c79356b 473
91447636 474 if (thread == THREAD_NULL)
1c79356b
A
475 return (KERN_INVALID_ARGUMENT);
476
91447636 477 thread_mtx_lock(thread);
9bccf70c 478
91447636
A
479 if (thread->active) {
480 if (thread != current_thread()) {
481 thread_hold(thread);
1c79356b 482
91447636 483 thread_mtx_unlock(thread);
9bccf70c 484
91447636
A
485 if (thread_stop(thread)) {
486 thread_mtx_lock(thread);
487 result = machine_thread_set_state(
488 thread, flavor, state, state_count);
489 thread_unstop(thread);
490 }
491 else {
492 thread_mtx_lock(thread);
493 result = KERN_ABORTED;
494 }
9bccf70c 495
91447636 496 thread_release(thread);
9bccf70c 497 }
91447636
A
498 else
499 result = machine_thread_set_state(
500 thread, flavor, state, state_count);
1c79356b 501 }
91447636
A
502 else
503 result = KERN_TERMINATED;
1c79356b 504
6d2010ae
A
505 if ((result == KERN_SUCCESS) && from_user)
506 extmod_statistics_incr_thread_set_state(thread);
507
91447636 508 thread_mtx_unlock(thread);
9bccf70c
A
509
510 return (result);
1c79356b 511}
6d2010ae
A
512
513/* No prototype, since thread_act_server.h has the _from_user version if KERNEL_SERVER */
514kern_return_t
515thread_set_state(
516 register thread_t thread,
517 int flavor,
518 thread_state_t state,
519 mach_msg_type_number_t state_count);
520
521kern_return_t
522thread_set_state(
523 register thread_t thread,
524 int flavor,
525 thread_state_t state,
526 mach_msg_type_number_t state_count)
527{
528 return thread_set_state_internal(thread, flavor, state, state_count, FALSE);
529}
91447636 530
6d2010ae
A
531kern_return_t
532thread_set_state_from_user(
533 register thread_t thread,
534 int flavor,
535 thread_state_t state,
536 mach_msg_type_number_t state_count)
537{
538 return thread_set_state_internal(thread, flavor, state, state_count, TRUE);
539}
91447636 540
1c79356b 541/*
91447636
A
542 * Kernel-internal "thread" interfaces used outside this file:
543 */
544
545/* Initialize (or re-initialize) a thread state. Called from execve
546 * with nothing locked, returns same way.
1c79356b
A
547 */
548kern_return_t
91447636
A
549thread_state_initialize(
550 register thread_t thread)
1c79356b 551{
9bccf70c 552 kern_return_t result = KERN_SUCCESS;
1c79356b 553
91447636 554 if (thread == THREAD_NULL)
1c79356b 555 return (KERN_INVALID_ARGUMENT);
1c79356b 556
91447636 557 thread_mtx_lock(thread);
9bccf70c 558
91447636
A
559 if (thread->active) {
560 if (thread != current_thread()) {
561 thread_hold(thread);
9bccf70c 562
91447636 563 thread_mtx_unlock(thread);
9bccf70c 564
91447636
A
565 if (thread_stop(thread)) {
566 thread_mtx_lock(thread);
567 result = machine_thread_state_initialize( thread );
568 thread_unstop(thread);
569 }
570 else {
571 thread_mtx_lock(thread);
572 result = KERN_ABORTED;
573 }
9bccf70c 574
91447636 575 thread_release(thread);
9bccf70c 576 }
91447636
A
577 else
578 result = machine_thread_state_initialize( thread );
1c79356b 579 }
91447636
A
580 else
581 result = KERN_TERMINATED;
9bccf70c 582
91447636 583 thread_mtx_unlock(thread);
9bccf70c
A
584
585 return (result);
1c79356b
A
586}
587
1c79356b
A
588
589kern_return_t
590thread_dup(
91447636 591 register thread_t target)
1c79356b 592{
91447636 593 thread_t self = current_thread();
9bccf70c 594 kern_return_t result = KERN_SUCCESS;
1c79356b 595
91447636 596 if (target == THREAD_NULL || target == self)
1c79356b
A
597 return (KERN_INVALID_ARGUMENT);
598
91447636 599 thread_mtx_lock(target);
9bccf70c 600
91447636
A
601 if (target->active) {
602 thread_hold(target);
9bccf70c 603
91447636 604 thread_mtx_unlock(target);
9bccf70c 605
91447636
A
606 if (thread_stop(target)) {
607 thread_mtx_lock(target);
608 result = machine_thread_dup(self, target);
2d21ac55
A
609 if (self->affinity_set != AFFINITY_SET_NULL)
610 thread_affinity_dup(self, target);
91447636
A
611 thread_unstop(target);
612 }
613 else {
614 thread_mtx_lock(target);
9bccf70c 615 result = KERN_ABORTED;
9bccf70c
A
616 }
617
91447636 618 thread_release(target);
1c79356b 619 }
91447636
A
620 else
621 result = KERN_TERMINATED;
9bccf70c 622
91447636 623 thread_mtx_unlock(target);
9bccf70c
A
624
625 return (result);
1c79356b
A
626}
627
628
629/*
630 * thread_setstatus:
631 *
632 * Set the status of the specified thread.
633 * Called with (and returns with) no locks held.
634 */
635kern_return_t
636thread_setstatus(
91447636 637 register thread_t thread,
9bccf70c
A
638 int flavor,
639 thread_state_t tstate,
1c79356b
A
640 mach_msg_type_number_t count)
641{
9bccf70c 642
91447636 643 return (thread_set_state(thread, flavor, tstate, count));
1c79356b
A
644}
645
646/*
647 * thread_getstatus:
648 *
649 * Get the status of the specified thread.
650 */
651kern_return_t
652thread_getstatus(
91447636 653 register thread_t thread,
9bccf70c
A
654 int flavor,
655 thread_state_t tstate,
1c79356b
A
656 mach_msg_type_number_t *count)
657{
91447636 658 return (thread_get_state(thread, flavor, tstate, count));
1c79356b
A
659}
660
661/*
91447636 662 * install_special_handler:
1c79356b 663 *
1c79356b
A
664 * Install the special returnhandler that handles suspension and
665 * termination, if it hasn't been installed already.
666 *
91447636 667 * Called with the thread mutex held.
1c79356b
A
668 */
669void
670install_special_handler(
91447636 671 thread_t thread)
1c79356b 672{
91447636 673 spl_t s = splsched();
1c79356b 674
e7c99d92 675 thread_lock(thread);
91447636 676 install_special_handler_locked(thread);
e7c99d92 677 thread_unlock(thread);
91447636 678 splx(s);
1c79356b
A
679}
680
681/*
91447636
A
682 * install_special_handler_locked:
683 *
1c79356b
A
684 * Do the work of installing the special_handler.
685 *
91447636 686 * Called with the thread mutex and scheduling lock held.
1c79356b
A
687 */
688void
689install_special_handler_locked(
91447636 690 thread_t thread)
1c79356b
A
691{
692 ReturnHandler **rh;
1c79356b
A
693
694 /* The work handler must always be the last ReturnHandler on the list,
695 because it can do tricky things like detach the thr_act. */
91447636 696 for (rh = &thread->handlers; *rh; rh = &(*rh)->next)
9bccf70c 697 continue;
1c79356b 698
91447636
A
699 if (rh != &thread->special_handler.next)
700 *rh = &thread->special_handler;
701
702 /*
703 * Temporarily undepress, so target has
704 * a chance to do locking required to
705 * block itself in special_handler().
706 */
6d2010ae
A
707 if (thread->sched_flags & TH_SFLAG_DEPRESSED_MASK)
708 SCHED(compute_priority)(thread, TRUE);
91447636
A
709
710 thread_ast_set(thread, AST_APC);
711
712 if (thread == current_thread())
713 ast_propagate(thread->ast);
9bccf70c
A
714 else {
715 processor_t processor = thread->last_processor;
716
55e303ae
A
717 if ( processor != PROCESSOR_NULL &&
718 processor->state == PROCESSOR_RUNNING &&
719 processor->active_thread == thread )
9bccf70c
A
720 cause_ast_check(processor);
721 }
722}
1c79356b 723
1c79356b
A
724/*
725 * Activation control support routines internal to this file:
726 */
727
9bccf70c
A
728void
729act_execute_returnhandlers(void)
1c79356b 730{
91447636 731 thread_t thread = current_thread();
1c79356b 732
91447636 733 thread_ast_clear(thread, AST_APC);
1c79356b 734 spllo();
1c79356b 735
9bccf70c
A
736 for (;;) {
737 ReturnHandler *rh;
91447636
A
738
739 thread_mtx_lock(thread);
9bccf70c 740
1c79356b
A
741 (void)splsched();
742 thread_lock(thread);
91447636
A
743
744 rh = thread->handlers;
745 if (rh != NULL) {
746 thread->handlers = rh->next;
747
1c79356b 748 thread_unlock(thread);
9bccf70c 749 spllo();
1c79356b 750
91447636
A
751 thread_mtx_unlock(thread);
752
753 /* Execute it */
754 (*rh->handler)(rh, thread);
755 }
756 else
757 break;
1c79356b 758 }
91447636
A
759
760 thread_unlock(thread);
761 spllo();
762
763 thread_mtx_unlock(thread);
1c79356b
A
764}
765
766/*
767 * special_handler_continue
768 *
769 * Continuation routine for the special handler blocks. It checks
770 * to see whether there has been any new suspensions. If so, it
771 * installs the special handler again. Otherwise, it checks to see
772 * if the current depression needs to be re-instated (it may have
773 * been temporarily removed in order to get to this point in a hurry).
774 */
775void
776special_handler_continue(void)
777{
91447636
A
778 thread_t thread = current_thread();
779
780 thread_mtx_lock(thread);
1c79356b 781
91447636
A
782 if (thread->suspend_count > 0)
783 install_special_handler(thread);
1c79356b 784 else {
9bccf70c
A
785 spl_t s = splsched();
786
1c79356b 787 thread_lock(thread);
6d2010ae 788 if (thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) {
9bccf70c
A
789 processor_t myprocessor = thread->last_processor;
790
791 thread->sched_pri = DEPRESSPRI;
792 myprocessor->current_pri = thread->sched_pri;
1c79356b
A
793 }
794 thread_unlock(thread);
795 splx(s);
796 }
9bccf70c 797
91447636
A
798 thread_mtx_unlock(thread);
799
1c79356b 800 thread_exception_return();
9bccf70c 801 /*NOTREACHED*/
1c79356b
A
802}
803
804/*
805 * special_handler - handles suspension, termination. Called
806 * with nothing locked. Returns (if it returns) the same way.
807 */
808void
809special_handler(
91447636
A
810 __unused ReturnHandler *rh,
811 thread_t thread)
1c79356b 812{
91447636 813 spl_t s;
1c79356b 814
91447636 815 thread_mtx_lock(thread);
1c79356b
A
816
817 s = splsched();
1c79356b 818 thread_lock(thread);
6d2010ae 819 thread->sched_flags &= ~TH_SFLAG_ABORTED_MASK;
1c79356b
A
820 thread_unlock(thread);
821 splx(s);
822
1c79356b
A
823 /*
824 * If we're suspended, go to sleep and wait for someone to wake us up.
825 */
91447636
A
826 if (thread->active) {
827 if (thread->suspend_count > 0) {
828 if (thread->handlers == NULL) {
829 assert_wait(&thread->suspend_count, THREAD_ABORTSAFE);
830 thread_mtx_unlock(thread);
831 thread_block((thread_continue_t)special_handler_continue);
832 /*NOTREACHED*/
833 }
9bccf70c 834
91447636 835 thread_mtx_unlock(thread);
9bccf70c 836
91447636
A
837 special_handler_continue();
838 /*NOTREACHED*/
9bccf70c 839 }
1c79356b 840 }
91447636
A
841 else {
842 thread_mtx_unlock(thread);
1c79356b 843
91447636
A
844 thread_terminate_self();
845 /*NOTREACHED*/
846 }
1c79356b 847
91447636 848 thread_mtx_unlock(thread);
1c79356b
A
849}
850
6d2010ae
A
851/* Prototype, see justification above */
852kern_return_t
853act_set_state(
854 thread_t thread,
855 int flavor,
856 thread_state_t state,
857 mach_msg_type_number_t count);
858
1c79356b 859kern_return_t
91447636
A
860act_set_state(
861 thread_t thread,
862 int flavor,
863 thread_state_t state,
864 mach_msg_type_number_t count)
1c79356b 865{
91447636
A
866 if (thread == current_thread())
867 return (KERN_INVALID_ARGUMENT);
1c79356b 868
91447636 869 return (thread_set_state(thread, flavor, state, count));
1c79356b
A
870
871}
872
6d2010ae
A
873kern_return_t
874act_set_state_from_user(
875 thread_t thread,
876 int flavor,
877 thread_state_t state,
878 mach_msg_type_number_t count)
879{
880 if (thread == current_thread())
881 return (KERN_INVALID_ARGUMENT);
882
883 return (thread_set_state_from_user(thread, flavor, state, count));
884
885}
886
1c79356b 887kern_return_t
91447636
A
888act_get_state(
889 thread_t thread,
890 int flavor,
891 thread_state_t state,
892 mach_msg_type_number_t *count)
1c79356b 893{
91447636
A
894 if (thread == current_thread())
895 return (KERN_INVALID_ARGUMENT);
1c79356b 896
91447636 897 return (thread_get_state(thread, flavor, state, count));
1c79356b
A
898}
899
1c79356b 900void
9bccf70c 901act_set_astbsd(
91447636 902 thread_t thread)
1c79356b 903{
91447636 904 spl_t s = splsched();
0b4e3aa0 905
91447636
A
906 if (thread == current_thread()) {
907 thread_ast_set(thread, AST_BSD);
908 ast_propagate(thread->ast);
1c79356b 909 }
9bccf70c 910 else {
9bccf70c 911 processor_t processor;
0b4e3aa0 912
9bccf70c 913 thread_lock(thread);
91447636 914 thread_ast_set(thread, AST_BSD);
9bccf70c 915 processor = thread->last_processor;
55e303ae
A
916 if ( processor != PROCESSOR_NULL &&
917 processor->state == PROCESSOR_RUNNING &&
918 processor->active_thread == thread )
9bccf70c
A
919 cause_ast_check(processor);
920 thread_unlock(thread);
0b4e3aa0
A
921 }
922
9bccf70c 923 splx(s);
1c79356b
A
924}
925
926void
9bccf70c 927act_set_apc(
91447636 928 thread_t thread)
1c79356b 929{
91447636 930 spl_t s = splsched();
9bccf70c 931
91447636
A
932 if (thread == current_thread()) {
933 thread_ast_set(thread, AST_APC);
934 ast_propagate(thread->ast);
9bccf70c
A
935 }
936 else {
9bccf70c
A
937 processor_t processor;
938
939 thread_lock(thread);
91447636 940 thread_ast_set(thread, AST_APC);
9bccf70c 941 processor = thread->last_processor;
55e303ae
A
942 if ( processor != PROCESSOR_NULL &&
943 processor->state == PROCESSOR_RUNNING &&
944 processor->active_thread == thread )
9bccf70c
A
945 cause_ast_check(processor);
946 thread_unlock(thread);
947 }
948
949 splx(s);
1c79356b 950}