]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/thread_act.c
xnu-517.11.1.tar.gz
[apple/xnu.git] / osfmk / kern / thread_act.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
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 *
e5568f75
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,
e5568f75
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 *
44 * Thread_Activation management routines
45 */
46
47#include <cpus.h>
48#include <task_swapper.h>
49#include <mach/kern_return.h>
50#include <mach/alert.h>
51#include <kern/etap_macros.h>
52#include <kern/mach_param.h>
53#include <kern/zalloc.h>
54#include <kern/thread.h>
55#include <kern/thread_swap.h>
56#include <kern/task.h>
57#include <kern/task_swap.h>
58#include <kern/thread_act.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>
1c79356b 70#include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/
0b4e3aa0 71#include <kern/processor.h>
1c79356b
A
72#include <mach_prof.h>
73#include <mach/rpc.h>
74
1c79356b
A
75/*
76 * Track the number of times we need to swapin a thread to deallocate it.
77 */
78int act_free_swapin = 0;
79
80/*
81 * Forward declarations for functions local to this file.
82 */
9bccf70c 83kern_return_t act_abort( thread_act_t, boolean_t);
1c79356b 84void special_handler(ReturnHandler *, thread_act_t);
1c79356b
A
85kern_return_t act_set_state_locked(thread_act_t, int,
86 thread_state_t,
87 mach_msg_type_number_t);
88kern_return_t act_get_state_locked(thread_act_t, int,
89 thread_state_t,
90 mach_msg_type_number_t *);
9bccf70c 91void act_set_astbsd(thread_act_t);
1c79356b 92void act_set_apc(thread_act_t);
1c79356b
A
93void act_ulock_release_all(thread_act_t thr_act);
94
95void install_special_handler_locked(thread_act_t);
96
9bccf70c
A
97static void act_disable(thread_act_t);
98
1c79356b
A
99/*
100 * Thread interfaces accessed via a thread_activation:
101 */
102
103
104/*
105 * Internal routine to terminate a thread.
9bccf70c 106 * Sometimes called with task already locked.
1c79356b
A
107 */
108kern_return_t
109thread_terminate_internal(
9bccf70c 110 register thread_act_t act)
1c79356b 111{
9bccf70c
A
112 kern_return_t result;
113 thread_t thread;
1c79356b 114
9bccf70c 115 thread = act_lock_thread(act);
1c79356b 116
9bccf70c
A
117 if (!act->active) {
118 act_unlock_thread(act);
119 return (KERN_TERMINATED);
1c79356b
A
120 }
121
9bccf70c
A
122 act_disable(act);
123 result = act_abort(act, FALSE);
e7c99d92 124
1c79356b
A
125 /*
126 * Make sure this thread enters the kernel
9bccf70c
A
127 * Must unlock the act, but leave the shuttle
128 * captured in this act.
1c79356b
A
129 */
130 if (thread != current_thread()) {
9bccf70c 131 act_unlock(act);
1c79356b 132
9bccf70c 133 if (thread_stop(thread))
e7c99d92
A
134 thread_unstop(thread);
135 else
9bccf70c 136 result = KERN_ABORTED;
1c79356b 137
9bccf70c 138 act_lock(act);
1c79356b 139 }
1c79356b 140
55e303ae 141 clear_wait(thread, act->started? THREAD_INTERRUPTED: THREAD_AWAKENED);
9bccf70c
A
142 act_unlock_thread(act);
143
144 return (result);
1c79356b
A
145}
146
147/*
9bccf70c 148 * Terminate a thread.
1c79356b
A
149 */
150kern_return_t
151thread_terminate(
9bccf70c 152 register thread_act_t act)
1c79356b 153{
9bccf70c 154 kern_return_t result;
1c79356b 155
9bccf70c
A
156 if (act == THR_ACT_NULL)
157 return (KERN_INVALID_ARGUMENT);
1c79356b 158
55e303ae 159 if ( act->task == kernel_task &&
9bccf70c
A
160 act != current_act() )
161 return (KERN_FAILURE);
1c79356b 162
9bccf70c 163 result = thread_terminate_internal(act);
1c79356b
A
164
165 /*
166 * If a kernel thread is terminating itself, force an AST here.
167 * Kernel threads don't normally pass through the AST checking
168 * code - and all threads finish their own termination in the
169 * special handler APC.
170 */
55e303ae
A
171 if (act->task == kernel_task) {
172 ml_set_interrupts_enabled(FALSE);
9bccf70c 173 assert(act == current_act());
55e303ae 174 ast_taken(AST_APC, TRUE);
9bccf70c
A
175 panic("thread_terminate");
176 }
1c79356b 177
9bccf70c 178 return (result);
1c79356b
A
179}
180
181/*
9bccf70c
A
182 * Suspend execution of the specified thread.
183 * This is a recursive-style suspension of the thread, a count of
184 * suspends is maintained.
1c79356b 185 *
9bccf70c 186 * Called with act_lock held.
1c79356b
A
187 */
188void
189thread_hold(
9bccf70c 190 register thread_act_t act)
1c79356b 191{
9bccf70c
A
192 thread_t thread = act->thread;
193
194 if (act->suspend_count++ == 0) {
195 install_special_handler(act);
55e303ae 196 if ( act->started &&
9bccf70c
A
197 thread != THREAD_NULL &&
198 thread->top_act == act )
199 thread_wakeup_one(&act->suspend_count);
1c79356b
A
200 }
201}
202
203/*
204 * Decrement internal suspension count for thr_act, setting thread
205 * runnable when count falls to zero.
206 *
9bccf70c 207 * Called with act_lock held.
1c79356b
A
208 */
209void
210thread_release(
9bccf70c 211 register thread_act_t act)
1c79356b 212{
9bccf70c
A
213 thread_t thread = act->thread;
214
215 if ( act->suspend_count > 0 &&
216 --act->suspend_count == 0 &&
217 thread != THREAD_NULL &&
218 thread->top_act == act ) {
55e303ae 219 if (!act->started) {
9bccf70c 220 clear_wait(thread, THREAD_AWAKENED);
55e303ae 221 act->started = TRUE;
9bccf70c
A
222 }
223 else
224 thread_wakeup_one(&act->suspend_count);
225 }
1c79356b
A
226}
227
228kern_return_t
229thread_suspend(
9bccf70c 230 register thread_act_t act)
1c79356b 231{
9bccf70c 232 thread_t thread;
1c79356b 233
55e303ae 234 if (act == THR_ACT_NULL || act->task == kernel_task)
9bccf70c
A
235 return (KERN_INVALID_ARGUMENT);
236
237 thread = act_lock_thread(act);
238
239 if (!act->active) {
240 act_unlock_thread(act);
241 return (KERN_TERMINATED);
1c79356b 242 }
9bccf70c
A
243
244 if ( act->user_stop_count++ == 0 &&
245 act->suspend_count++ == 0 ) {
246 install_special_handler(act);
247 if ( thread != current_thread() &&
248 thread != THREAD_NULL &&
249 thread->top_act == act ) {
55e303ae 250 assert(act->started);
9bccf70c
A
251 thread_wakeup_one(&act->suspend_count);
252 act_unlock_thread(act);
253
254 thread_wait(thread);
1c79356b 255 }
9bccf70c
A
256 else
257 act_unlock_thread(act);
1c79356b 258 }
9bccf70c
A
259 else
260 act_unlock_thread(act);
261
262 return (KERN_SUCCESS);
1c79356b
A
263}
264
265kern_return_t
266thread_resume(
9bccf70c 267 register thread_act_t act)
1c79356b 268{
9bccf70c 269 kern_return_t result = KERN_SUCCESS;
1c79356b
A
270 thread_t thread;
271
55e303ae 272 if (act == THR_ACT_NULL || act->task == kernel_task)
9bccf70c 273 return (KERN_INVALID_ARGUMENT);
1c79356b 274
9bccf70c
A
275 thread = act_lock_thread(act);
276
277 if (act->active) {
278 if (act->user_stop_count > 0) {
279 if ( --act->user_stop_count == 0 &&
280 --act->suspend_count == 0 &&
281 thread != THREAD_NULL &&
282 thread->top_act == act ) {
55e303ae 283 if (!act->started) {
9bccf70c 284 clear_wait(thread, THREAD_AWAKENED);
55e303ae 285 act->started = TRUE;
9bccf70c
A
286 }
287 else
288 thread_wakeup_one(&act->suspend_count);
1c79356b
A
289 }
290 }
291 else
9bccf70c 292 result = KERN_FAILURE;
1c79356b
A
293 }
294 else
9bccf70c
A
295 result = KERN_TERMINATED;
296
297 act_unlock_thread(act);
298
299 return (result);
1c79356b
A
300}
301
1c79356b
A
302/*
303 * thread_depress_abort:
304 *
305 * Prematurely abort priority depression if there is one.
306 */
307kern_return_t
308thread_depress_abort(
309 register thread_act_t thr_act)
310{
311 register thread_t thread;
312 kern_return_t result;
1c79356b
A
313
314 if (thr_act == THR_ACT_NULL)
315 return (KERN_INVALID_ARGUMENT);
316
317 thread = act_lock_thread(thr_act);
318 /* if activation is terminating, this operation is not meaningful */
319 if (!thr_act->active) {
320 act_unlock_thread(thr_act);
321
322 return (KERN_TERMINATED);
323 }
324
0b4e3aa0 325 result = _mk_sp_thread_depress_abort(thread, FALSE);
1c79356b
A
326
327 act_unlock_thread(thr_act);
328
329 return (result);
330}
331
332
333/*
9bccf70c
A
334 * Indicate that the activation should run its
335 * special handler to detect the condition.
336 *
337 * Called with act_lock held.
1c79356b
A
338 */
339kern_return_t
9bccf70c
A
340act_abort(
341 thread_act_t act,
342 boolean_t chain_break )
1c79356b 343{
9bccf70c
A
344 thread_t thread = act->thread;
345 spl_t s = splsched();
1c79356b 346
9bccf70c 347 assert(thread->top_act == act);
1c79356b 348
9bccf70c
A
349 thread_lock(thread);
350 if (!(thread->state & TH_ABORT)) {
351 thread->state |= TH_ABORT;
352 install_special_handler_locked(act);
353 } else {
354 thread->state &= ~TH_ABORT_SAFELY;
1c79356b 355 }
9bccf70c
A
356 thread_unlock(thread);
357 splx(s);
1c79356b 358
9bccf70c 359 return (KERN_SUCCESS);
1c79356b
A
360}
361
362kern_return_t
363thread_abort(
9bccf70c 364 register thread_act_t act)
1c79356b 365{
9bccf70c 366 kern_return_t result;
1c79356b
A
367 thread_t thread;
368
9bccf70c 369 if (act == THR_ACT_NULL)
1c79356b 370 return (KERN_INVALID_ARGUMENT);
9bccf70c
A
371
372 thread = act_lock_thread(act);
373
374 if (!act->active) {
375 act_unlock_thread(act);
376 return (KERN_TERMINATED);
1c79356b
A
377 }
378
9bccf70c
A
379 result = act_abort(act, FALSE);
380 clear_wait(thread, THREAD_INTERRUPTED);
381 act_unlock_thread(act);
382
383 return (result);
1c79356b
A
384}
385
386kern_return_t
387thread_abort_safely(
9bccf70c 388 thread_act_t act)
1c79356b
A
389{
390 thread_t thread;
9bccf70c 391 kern_return_t ret;
1c79356b
A
392 spl_t s;
393
9bccf70c
A
394 if ( act == THR_ACT_NULL )
395 return (KERN_INVALID_ARGUMENT);
1c79356b 396
9bccf70c
A
397 thread = act_lock_thread(act);
398
399 if (!act->active) {
400 act_unlock_thread(act);
401 return (KERN_TERMINATED);
1c79356b 402 }
9bccf70c 403
1c79356b
A
404 s = splsched();
405 thread_lock(thread);
9bccf70c
A
406 if (!thread->at_safe_point ||
407 clear_wait_internal(thread, THREAD_INTERRUPTED) != KERN_SUCCESS) {
408 if (!(thread->state & TH_ABORT)) {
409 thread->state |= (TH_ABORT|TH_ABORT_SAFELY);
410 install_special_handler_locked(act);
411 }
1c79356b 412 }
1c79356b 413 thread_unlock(thread);
1c79356b 414 splx(s);
9bccf70c
A
415
416 act_unlock_thread(act);
417
418 return (KERN_SUCCESS);
1c79356b
A
419}
420
421/*** backward compatibility hacks ***/
422#include <mach/thread_info.h>
423#include <mach/thread_special_ports.h>
424#include <ipc/ipc_port.h>
425#include <mach/thread_act_server.h>
426
427kern_return_t
428thread_info(
429 thread_act_t thr_act,
430 thread_flavor_t flavor,
431 thread_info_t thread_info_out,
432 mach_msg_type_number_t *thread_info_count)
433{
434 register thread_t thread;
435 kern_return_t result;
436
437 if (thr_act == THR_ACT_NULL)
438 return (KERN_INVALID_ARGUMENT);
439
440 thread = act_lock_thread(thr_act);
441 if (!thr_act->active) {
442 act_unlock_thread(thr_act);
443
444 return (KERN_TERMINATED);
445 }
446
447 result = thread_info_shuttle(thr_act, flavor,
448 thread_info_out, thread_info_count);
449
450 act_unlock_thread(thr_act);
451
452 return (result);
453}
454
455/*
456 * Routine: thread_get_special_port [kernel call]
457 * Purpose:
458 * Clones a send right for one of the thread's
459 * special ports.
460 * Conditions:
461 * Nothing locked.
462 * Returns:
463 * KERN_SUCCESS Extracted a send right.
464 * KERN_INVALID_ARGUMENT The thread is null.
465 * KERN_FAILURE The thread is dead.
466 * KERN_INVALID_ARGUMENT Invalid special port.
467 */
468
469kern_return_t
470thread_get_special_port(
471 thread_act_t thr_act,
472 int which,
473 ipc_port_t *portp)
474{
475 ipc_port_t *whichp;
476 ipc_port_t port;
477 thread_t thread;
478
1c79356b
A
479 if (!thr_act)
480 return KERN_INVALID_ARGUMENT;
481 thread = act_lock_thread(thr_act);
482 switch (which) {
483 case THREAD_KERNEL_PORT:
484 whichp = &thr_act->ith_sself;
485 break;
486
487 default:
488 act_unlock_thread(thr_act);
489 return KERN_INVALID_ARGUMENT;
490 }
491
492 if (!thr_act->active) {
493 act_unlock_thread(thr_act);
494 return KERN_FAILURE;
495 }
496
497 port = ipc_port_copy_send(*whichp);
498 act_unlock_thread(thr_act);
499
500 *portp = port;
501 return KERN_SUCCESS;
502}
503
504/*
505 * Routine: thread_set_special_port [kernel call]
506 * Purpose:
507 * Changes one of the thread's special ports,
508 * setting it to the supplied send right.
509 * Conditions:
510 * Nothing locked. If successful, consumes
511 * the supplied send right.
512 * Returns:
513 * KERN_SUCCESS Changed the special port.
514 * KERN_INVALID_ARGUMENT The thread is null.
515 * KERN_FAILURE The thread is dead.
516 * KERN_INVALID_ARGUMENT Invalid special port.
517 */
518
519kern_return_t
520thread_set_special_port(
521 thread_act_t thr_act,
522 int which,
523 ipc_port_t port)
524{
525 ipc_port_t *whichp;
526 ipc_port_t old;
527 thread_t thread;
528
1c79356b
A
529 if (thr_act == 0)
530 return KERN_INVALID_ARGUMENT;
531
532 thread = act_lock_thread(thr_act);
533 switch (which) {
534 case THREAD_KERNEL_PORT:
535 whichp = &thr_act->ith_self;
536 break;
537
538 default:
539 act_unlock_thread(thr_act);
540 return KERN_INVALID_ARGUMENT;
541 }
542
543 if (!thr_act->active) {
544 act_unlock_thread(thr_act);
545 return KERN_FAILURE;
546 }
547
548 old = *whichp;
549 *whichp = port;
550 act_unlock_thread(thr_act);
551
552 if (IP_VALID(old))
553 ipc_port_release_send(old);
554 return KERN_SUCCESS;
555}
556
557/*
558 * thread state should always be accessible by locking the thread
559 * and copying it. The activation messes things up so for right
560 * now if it's not the top of the chain, use a special handler to
561 * get the information when the shuttle returns to the activation.
562 */
563kern_return_t
564thread_get_state(
9bccf70c
A
565 register thread_act_t act,
566 int flavor,
567 thread_state_t state, /* pointer to OUT array */
1c79356b
A
568 mach_msg_type_number_t *state_count) /*IN/OUT*/
569{
9bccf70c
A
570 kern_return_t result = KERN_SUCCESS;
571 thread_t thread;
1c79356b 572
9bccf70c 573 if (act == THR_ACT_NULL || act == current_act())
1c79356b
A
574 return (KERN_INVALID_ARGUMENT);
575
9bccf70c
A
576 thread = act_lock_thread(act);
577
578 if (!act->active) {
579 act_unlock_thread(act);
580 return (KERN_TERMINATED);
1c79356b
A
581 }
582
9bccf70c
A
583 thread_hold(act);
584
585 for (;;) {
586 thread_t thread1;
587
588 if ( thread == THREAD_NULL ||
589 thread->top_act != act )
1c79356b 590 break;
9bccf70c
A
591 act_unlock_thread(act);
592
593 if (!thread_stop(thread)) {
594 result = KERN_ABORTED;
595 (void)act_lock_thread(act);
596 thread = THREAD_NULL;
597 break;
598 }
599
600 thread1 = act_lock_thread(act);
601 if (thread1 == thread)
1c79356b 602 break;
9bccf70c 603
1c79356b 604 thread_unstop(thread);
9bccf70c 605 thread = thread1;
1c79356b 606 }
1c79356b 607
9bccf70c 608 if (result == KERN_SUCCESS)
55e303ae 609 result = machine_thread_get_state(act, flavor, state, state_count);
9bccf70c
A
610
611 if ( thread != THREAD_NULL &&
612 thread->top_act == act )
613 thread_unstop(thread);
614
615 thread_release(act);
616 act_unlock_thread(act);
617
618 return (result);
1c79356b
A
619}
620
621/*
622 * Change thread's machine-dependent state. Called with nothing
623 * locked. Returns same way.
624 */
625kern_return_t
626thread_set_state(
9bccf70c
A
627 register thread_act_t act,
628 int flavor,
629 thread_state_t state,
1c79356b
A
630 mach_msg_type_number_t state_count)
631{
9bccf70c
A
632 kern_return_t result = KERN_SUCCESS;
633 thread_t thread;
1c79356b 634
9bccf70c 635 if (act == THR_ACT_NULL || act == current_act())
1c79356b 636 return (KERN_INVALID_ARGUMENT);
1c79356b 637
9bccf70c
A
638 thread = act_lock_thread(act);
639
640 if (!act->active) {
641 act_unlock_thread(act);
642 return (KERN_TERMINATED);
1c79356b
A
643 }
644
9bccf70c
A
645 thread_hold(act);
646
647 for (;;) {
648 thread_t thread1;
649
650 if ( thread == THREAD_NULL ||
651 thread->top_act != act )
1c79356b 652 break;
9bccf70c
A
653 act_unlock_thread(act);
654
655 if (!thread_stop(thread)) {
656 result = KERN_ABORTED;
657 (void)act_lock_thread(act);
658 thread = THREAD_NULL;
1c79356b 659 break;
9bccf70c
A
660 }
661
662 thread1 = act_lock_thread(act);
663 if (thread1 == thread)
664 break;
665
1c79356b 666 thread_unstop(thread);
9bccf70c 667 thread = thread1;
1c79356b 668 }
9bccf70c
A
669
670 if (result == KERN_SUCCESS)
55e303ae 671 result = machine_thread_set_state(act, flavor, state, state_count);
9bccf70c
A
672
673 if ( thread != THREAD_NULL &&
674 thread->top_act == act )
1c79356b 675 thread_unstop(thread);
1c79356b 676
9bccf70c
A
677 thread_release(act);
678 act_unlock_thread(act);
679
680 return (result);
1c79356b
A
681}
682
683/*
684 * Kernel-internal "thread" interfaces used outside this file:
685 */
686
687kern_return_t
688thread_dup(
9bccf70c 689 register thread_act_t target)
1c79356b 690{
9bccf70c
A
691 kern_return_t result = KERN_SUCCESS;
692 thread_act_t self = current_act();
693 thread_t thread;
1c79356b 694
9bccf70c 695 if (target == THR_ACT_NULL || target == self)
1c79356b
A
696 return (KERN_INVALID_ARGUMENT);
697
9bccf70c
A
698 thread = act_lock_thread(target);
699
700 if (!target->active) {
701 act_unlock_thread(target);
702 return (KERN_TERMINATED);
1c79356b
A
703 }
704
9bccf70c
A
705 thread_hold(target);
706
707 for (;;) {
708 thread_t thread1;
709
710 if ( thread == THREAD_NULL ||
711 thread->top_act != target )
712 break;
713 act_unlock_thread(target);
714
715 if (!thread_stop(thread)) {
716 result = KERN_ABORTED;
717 (void)act_lock_thread(target);
718 thread = THREAD_NULL;
1c79356b 719 break;
9bccf70c
A
720 }
721
722 thread1 = act_lock_thread(target);
723 if (thread1 == thread)
1c79356b 724 break;
9bccf70c 725
1c79356b 726 thread_unstop(thread);
9bccf70c 727 thread = thread1;
1c79356b 728 }
9bccf70c
A
729
730 if (result == KERN_SUCCESS)
55e303ae 731 result = machine_thread_dup(self, target);
9bccf70c
A
732
733 if ( thread != THREAD_NULL &&
734 thread->top_act == target )
1c79356b 735 thread_unstop(thread);
1c79356b 736
9bccf70c
A
737 thread_release(target);
738 act_unlock_thread(target);
739
740 return (result);
1c79356b
A
741}
742
743
744/*
745 * thread_setstatus:
746 *
747 * Set the status of the specified thread.
748 * Called with (and returns with) no locks held.
749 */
750kern_return_t
751thread_setstatus(
9bccf70c
A
752 register thread_act_t act,
753 int flavor,
754 thread_state_t tstate,
1c79356b
A
755 mach_msg_type_number_t count)
756{
9bccf70c
A
757 kern_return_t result = KERN_SUCCESS;
758 thread_t thread;
1c79356b 759
9bccf70c
A
760 thread = act_lock_thread(act);
761
762 if ( act != current_act() &&
763 (act->suspend_count == 0 ||
764 thread == THREAD_NULL ||
765 (thread->state & TH_RUN) ||
766 thread->top_act != act) )
767 result = KERN_FAILURE;
768
769 if (result == KERN_SUCCESS)
55e303ae 770 result = machine_thread_set_state(act, flavor, tstate, count);
9bccf70c
A
771
772 act_unlock_thread(act);
773
774 return (result);
1c79356b
A
775}
776
777/*
778 * thread_getstatus:
779 *
780 * Get the status of the specified thread.
781 */
782kern_return_t
783thread_getstatus(
9bccf70c
A
784 register thread_act_t act,
785 int flavor,
786 thread_state_t tstate,
1c79356b
A
787 mach_msg_type_number_t *count)
788{
9bccf70c
A
789 kern_return_t result = KERN_SUCCESS;
790 thread_t thread;
1c79356b 791
9bccf70c
A
792 thread = act_lock_thread(act);
793
794 if ( act != current_act() &&
795 (act->suspend_count == 0 ||
796 thread == THREAD_NULL ||
797 (thread->state & TH_RUN) ||
798 thread->top_act != act) )
799 result = KERN_FAILURE;
800
801 if (result == KERN_SUCCESS)
55e303ae 802 result = machine_thread_get_state(act, flavor, tstate, count);
9bccf70c
A
803
804 act_unlock_thread(act);
805
806 return (result);
1c79356b
A
807}
808
809/*
810 * Kernel-internal thread_activation interfaces used outside this file:
811 */
812
1c79356b 813void
55e303ae
A
814act_reference(
815 thread_act_t act)
1c79356b 816{
55e303ae
A
817 if (act == NULL)
818 return;
1c79356b 819
55e303ae
A
820 act_lock(act);
821 act_reference_locked(act);
822 act_unlock(act);
823}
1c79356b 824
55e303ae
A
825void
826act_deallocate(
827 thread_act_t act)
1c79356b 828{
55e303ae
A
829 task_t task;
830 thread_t thread;
831 void *task_proc;
1c79356b 832
55e303ae
A
833 if (act == NULL)
834 return;
1c79356b 835
55e303ae 836 act_lock(act);
1c79356b 837
55e303ae
A
838 if (--act->act_ref_count > 0) {
839 act_unlock(act);
840 return;
1c79356b
A
841 }
842
55e303ae 843 assert(!act->active);
1c79356b 844
55e303ae
A
845 thread = act->thread;
846 assert(thread != NULL);
1c79356b 847
55e303ae 848 thread->top_act = NULL;
1c79356b 849
55e303ae 850 act_unlock(act);
1c79356b 851
55e303ae 852 task = act->task;
1c79356b
A
853 task_lock(task);
854
9bccf70c 855 task_proc = task->bsd_info;
55e303ae
A
856
857 {
1c79356b
A
858 time_value_t user_time, system_time;
859
55e303ae 860 thread_read_times(thread, &user_time, &system_time);
1c79356b
A
861 time_value_add(&task->total_user_time, &user_time);
862 time_value_add(&task->total_system_time, &system_time);
863
55e303ae
A
864 queue_remove(&task->threads, act, thread_act_t, task_threads);
865 act->task_threads.next = NULL;
866 task->thread_count--;
867 task->res_thread_count--;
1c79356b
A
868 }
869
55e303ae 870 task_unlock(task);
1c79356b 871
55e303ae
A
872 act_prof_deallocate(act);
873 ipc_thr_act_terminate(act);
1c79356b
A
874
875#ifdef MACH_BSD
876 {
e5568f75 877 extern void uthread_free(task_t, void *, void *, void *);
55e303ae 878 void *ut = act->uthread;
9bccf70c 879
e5568f75 880 uthread_free(task, act, ut, task_proc);
55e303ae 881 act->uthread = NULL;
1c79356b
A
882 }
883#endif /* MACH_BSD */
884
55e303ae
A
885 task_deallocate(task);
886
887 thread_deallocate(thread);
1c79356b
A
888}
889
890
891/*
892 * act_attach - Attach an thr_act to the top of a thread ("push the stack").
893 *
894 * The thread_shuttle must be either the current one or a brand-new one.
9bccf70c 895 * Assumes the thr_act is active but not in use.
1c79356b
A
896 *
897 * Already locked: thr_act plus "appropriate" thread-related locks
898 * (see act_lock_thread()).
899 */
900void
901act_attach(
55e303ae
A
902 thread_act_t act,
903 thread_t thread)
1c79356b 904{
55e303ae 905 thread_act_t lower;
1c79356b
A
906
907 /*
55e303ae 908 * Chain the act onto the thread's act stack.
1c79356b 909 */
55e303ae
A
910 act->act_ref_count++;
911 act->thread = thread;
912 act->higher = THR_ACT_NULL;
913 lower = act->lower = thread->top_act;
914 if (lower != THR_ACT_NULL)
915 lower->higher = act;
916
917 thread->top_act = act;
1c79356b
A
918}
919
920/*
921 * act_detach
922 *
923 * Remove the current thr_act from the top of the current thread, i.e.
924 * "pop the stack". Assumes already locked: thr_act plus "appropriate"
925 * thread-related locks (see act_lock_thread).
926 */
927void
928act_detach(
929 thread_act_t cur_act)
930{
931 thread_t cur_thread = cur_act->thread;
932
1c79356b
A
933 /* Unlink the thr_act from the thread's thr_act stack */
934 cur_thread->top_act = cur_act->lower;
935 cur_act->thread = 0;
55e303ae
A
936 cur_act->act_ref_count--;
937 assert(cur_act->act_ref_count > 0);
1c79356b 938
1c79356b
A
939#if MACH_ASSERT
940 cur_act->lower = cur_act->higher = THR_ACT_NULL;
941 if (cur_thread->top_act)
942 cur_thread->top_act->higher = THR_ACT_NULL;
943#endif /* MACH_ASSERT */
944
945 return;
946}
947
948
949/*
9bccf70c
A
950 * Synchronize a thread operation with migration.
951 * Called with nothing locked.
952 * Returns with thr_act locked.
1c79356b
A
953 */
954thread_t
955act_lock_thread(
956 thread_act_t thr_act)
957{
1c79356b
A
958
959 /*
9bccf70c
A
960 * JMM - We have moved away from explicit RPC locks
961 * and towards a generic migration approach. The wait
962 * queue lock will be the point of synchronization for
963 * the shuttle linkage when this is rolled out. Until
964 * then, just lock the act.
1c79356b 965 */
9bccf70c 966 act_lock(thr_act);
1c79356b
A
967 return (thr_act->thread);
968}
969
970/*
9bccf70c 971 * Unsynchronize with migration (i.e., undo an act_lock_thread() call).
1c79356b
A
972 * Called with thr_act locked, plus thread locks held that are
973 * "correct" for thr_act's state. Returns with nothing locked.
974 */
975void
976act_unlock_thread(thread_act_t thr_act)
977{
1c79356b
A
978 act_unlock(thr_act);
979}
980
981/*
9bccf70c 982 * Synchronize with migration given a pointer to a shuttle (instead of an
1c79356b
A
983 * activation). Called with nothing locked; returns with all
984 * "appropriate" thread-related locks held (see act_lock_thread()).
985 */
986thread_act_t
987thread_lock_act(
988 thread_t thread)
989{
990 thread_act_t thr_act;
991
992 while (1) {
1c79356b
A
993 thr_act = thread->top_act;
994 if (!thr_act)
995 break;
996 if (!act_lock_try(thr_act)) {
1c79356b
A
997 mutex_pause();
998 continue;
999 }
1000 break;
1001 }
1002 return (thr_act);
1003}
1004
1005/*
9bccf70c
A
1006 * Unsynchronize with an activation starting from a pointer to
1007 * a shuttle.
1c79356b
A
1008 */
1009void
1010thread_unlock_act(
1011 thread_t thread)
1012{
1013 thread_act_t thr_act;
1014
1015 if (thr_act = thread->top_act) {
1c79356b
A
1016 act_unlock(thr_act);
1017 }
1c79356b
A
1018}
1019
1020/*
1021 * switch_act
1022 *
1023 * If a new activation is given, switch to it. If not,
1024 * switch to the lower activation (pop). Returns the old
9bccf70c 1025 * activation. This is for migration support.
1c79356b
A
1026 */
1027thread_act_t
1028switch_act(
1029 thread_act_t act)
1030{
1c79356b 1031 thread_act_t old, new;
55e303ae 1032 thread_t thread;
1c79356b
A
1033
1034 disable_preemption();
1035
1c79356b
A
1036 thread = current_thread();
1037
1038 /*
1039 * Find the old and new activation for switch.
1040 */
1041 old = thread->top_act;
1042
1043 if (act) {
1044 new = act;
1045 new->thread = thread;
1046 }
1047 else {
1048 new = old->lower;
1049 }
1050
1051 assert(new != THR_ACT_NULL);
55e303ae 1052 assert(current_processor()->active_thread == thread);
1c79356b
A
1053
1054 /* This is where all the work happens */
55e303ae 1055 machine_switch_act(thread, old, new);
1c79356b
A
1056
1057 /*
1058 * Push or pop an activation on the chain.
1059 */
1060 if (act) {
55e303ae 1061 act_attach(new, thread);
1c79356b
A
1062 }
1063 else {
1064 act_detach(old);
1065 }
1066
1067 enable_preemption();
1068
1069 return(old);
1070}
1071
1072/*
1073 * install_special_handler
1074 * Install the special returnhandler that handles suspension and
1075 * termination, if it hasn't been installed already.
1076 *
1077 * Already locked: RPC-related locks for thr_act, but not
1078 * scheduling lock (thread_lock()) of the associated thread.
1079 */
1080void
1081install_special_handler(
1082 thread_act_t thr_act)
1083{
1084 spl_t spl;
1085 thread_t thread = thr_act->thread;
1086
1c79356b 1087 spl = splsched();
e7c99d92 1088 thread_lock(thread);
1c79356b 1089 install_special_handler_locked(thr_act);
e7c99d92 1090 thread_unlock(thread);
1c79356b
A
1091 splx(spl);
1092}
1093
1094/*
1095 * install_special_handler_locked
1096 * Do the work of installing the special_handler.
1097 *
1098 * Already locked: RPC-related locks for thr_act, plus the
1099 * scheduling lock (thread_lock()) of the associated thread.
1100 */
1101void
1102install_special_handler_locked(
9bccf70c 1103 thread_act_t act)
1c79356b 1104{
9bccf70c 1105 thread_t thread = act->thread;
1c79356b 1106 ReturnHandler **rh;
1c79356b
A
1107
1108 /* The work handler must always be the last ReturnHandler on the list,
1109 because it can do tricky things like detach the thr_act. */
9bccf70c
A
1110 for (rh = &act->handlers; *rh; rh = &(*rh)->next)
1111 continue;
1112 if (rh != &act->special_handler.next)
1113 *rh = &act->special_handler;
1114
1115 if (act == thread->top_act) {
1c79356b
A
1116 /*
1117 * Temporarily undepress, so target has
1118 * a chance to do locking required to
1119 * block itself in special_handler().
1120 */
9bccf70c
A
1121 if (thread->sched_mode & TH_MODE_ISDEPRESSED)
1122 compute_priority(thread, TRUE);
1c79356b 1123 }
1c79356b 1124
9bccf70c
A
1125 thread_ast_set(act, AST_APC);
1126 if (act == current_act())
1127 ast_propagate(act->ast);
1128 else {
1129 processor_t processor = thread->last_processor;
1130
55e303ae
A
1131 if ( processor != PROCESSOR_NULL &&
1132 processor->state == PROCESSOR_RUNNING &&
1133 processor->active_thread == thread )
9bccf70c
A
1134 cause_ast_check(processor);
1135 }
1136}
1c79356b
A
1137
1138kern_return_t
1139thread_apc_set(
9bccf70c
A
1140 thread_act_t act,
1141 thread_apc_handler_t apc)
1c79356b 1142{
9bccf70c
A
1143 extern thread_apc_handler_t bsd_ast;
1144
1c79356b 1145 assert(apc == bsd_ast);
9bccf70c 1146 return (KERN_FAILURE);
1c79356b
A
1147}
1148
1149kern_return_t
1150thread_apc_clear(
9bccf70c
A
1151 thread_act_t act,
1152 thread_apc_handler_t apc)
1c79356b 1153{
9bccf70c 1154 extern thread_apc_handler_t bsd_ast;
1c79356b 1155
9bccf70c
A
1156 assert(apc == bsd_ast);
1157 return (KERN_FAILURE);
1c79356b
A
1158}
1159
1160/*
1161 * Activation control support routines internal to this file:
1162 */
1163
1164/*
1165 * act_execute_returnhandlers() - does just what the name says
1166 *
1167 * This is called by system-dependent code when it detects that
1168 * thr_act->handlers is non-null while returning into user mode.
1c79356b 1169 */
9bccf70c
A
1170void
1171act_execute_returnhandlers(void)
1c79356b 1172{
9bccf70c 1173 thread_act_t act = current_act();
1c79356b 1174
9bccf70c 1175 thread_ast_clear(act, AST_APC);
1c79356b 1176 spllo();
1c79356b 1177
9bccf70c
A
1178 for (;;) {
1179 ReturnHandler *rh;
1180 thread_t thread = act_lock_thread(act);
1181
1c79356b
A
1182 (void)splsched();
1183 thread_lock(thread);
9bccf70c 1184 rh = act->handlers;
1c79356b
A
1185 if (!rh) {
1186 thread_unlock(thread);
9bccf70c
A
1187 spllo();
1188 act_unlock_thread(act);
1c79356b
A
1189 return;
1190 }
9bccf70c 1191 act->handlers = rh->next;
1c79356b
A
1192 thread_unlock(thread);
1193 spllo();
9bccf70c 1194 act_unlock_thread(act);
1c79356b 1195
1c79356b 1196 /* Execute it */
9bccf70c 1197 (*rh->handler)(rh, act);
1c79356b
A
1198 }
1199}
1200
1201/*
1202 * special_handler_continue
1203 *
1204 * Continuation routine for the special handler blocks. It checks
1205 * to see whether there has been any new suspensions. If so, it
1206 * installs the special handler again. Otherwise, it checks to see
1207 * if the current depression needs to be re-instated (it may have
1208 * been temporarily removed in order to get to this point in a hurry).
1209 */
1210void
1211special_handler_continue(void)
1212{
9bccf70c 1213 thread_act_t self = current_act();
1c79356b 1214
9bccf70c
A
1215 if (self->suspend_count > 0)
1216 install_special_handler(self);
1c79356b 1217 else {
9bccf70c
A
1218 thread_t thread = self->thread;
1219 spl_t s = splsched();
1220
1c79356b 1221 thread_lock(thread);
9bccf70c
A
1222 if (thread->sched_mode & TH_MODE_ISDEPRESSED) {
1223 processor_t myprocessor = thread->last_processor;
1224
1225 thread->sched_pri = DEPRESSPRI;
1226 myprocessor->current_pri = thread->sched_pri;
1227 thread->sched_mode &= ~TH_MODE_PREEMPT;
1c79356b
A
1228 }
1229 thread_unlock(thread);
1230 splx(s);
1231 }
9bccf70c 1232
1c79356b 1233 thread_exception_return();
9bccf70c 1234 /*NOTREACHED*/
1c79356b
A
1235}
1236
1237/*
1238 * special_handler - handles suspension, termination. Called
1239 * with nothing locked. Returns (if it returns) the same way.
1240 */
1241void
1242special_handler(
1243 ReturnHandler *rh,
9bccf70c 1244 thread_act_t self)
1c79356b 1245{
9bccf70c
A
1246 thread_t thread = act_lock_thread(self);
1247 spl_t s;
1c79356b
A
1248
1249 assert(thread != THREAD_NULL);
1c79356b
A
1250
1251 s = splsched();
1c79356b 1252 thread_lock(thread);
9bccf70c 1253 thread->state &= ~(TH_ABORT|TH_ABORT_SAFELY); /* clear any aborts */
1c79356b
A
1254 thread_unlock(thread);
1255 splx(s);
1256
9bccf70c
A
1257 if (!self->active) {
1258 act_unlock_thread(self);
55e303ae
A
1259 thread_terminate_self();
1260 /*NOTREACHED*/
1c79356b
A
1261 }
1262
1c79356b
A
1263 /*
1264 * If we're suspended, go to sleep and wait for someone to wake us up.
1265 */
9bccf70c
A
1266 if (self->suspend_count > 0) {
1267 if (self->handlers == NULL) {
1268 assert_wait(&self->suspend_count, THREAD_ABORTSAFE);
1269 act_unlock_thread(self);
1c79356b 1270 thread_block(special_handler_continue);
55e303ae 1271 /*NOTREACHED*/
1c79356b 1272 }
1c79356b 1273
9bccf70c 1274 act_unlock_thread(self);
1c79356b 1275
9bccf70c
A
1276 special_handler_continue();
1277 /*NOTREACHED*/
1c79356b 1278 }
9bccf70c
A
1279
1280 act_unlock_thread(self);
1c79356b
A
1281}
1282
1c79356b 1283/*
9bccf70c 1284 * Already locked: activation (shuttle frozen within)
1c79356b 1285 *
9bccf70c 1286 * Mark an activation inactive, and prepare it to terminate
1c79356b
A
1287 * itself.
1288 */
9bccf70c
A
1289static void
1290act_disable(
1c79356b
A
1291 thread_act_t thr_act)
1292{
1c79356b 1293 thr_act->active = 0;
1c79356b
A
1294
1295 /* Drop the thr_act reference taken for being active.
1296 * (There is still at least one reference left:
1297 * the one we were passed.)
1298 * Inline the deallocate because thr_act is locked.
1299 */
55e303ae 1300 act_deallocate_locked(thr_act);
1c79356b
A
1301}
1302
1303typedef struct GetSetState {
1304 struct ReturnHandler rh;
1305 int flavor;
1306 void *state;
1307 int *pcount;
1308 int result;
1309} GetSetState;
1310
1311/* Local Forward decls */
1312kern_return_t get_set_state(
1313 thread_act_t thr_act, int flavor,
1314 thread_state_t state, int *pcount,
1315 void (*handler)(ReturnHandler *rh, thread_act_t thr_act));
1316void get_state_handler(ReturnHandler *rh, thread_act_t thr_act);
1317void set_state_handler(ReturnHandler *rh, thread_act_t thr_act);
1318
1319/*
1320 * get_set_state(thr_act ...)
1321 *
1322 * General code to install g/set_state handler.
1323 * Called with thr_act's act_lock() and "appropriate"
1324 * thread-related locks held. (See act_lock_thread().)
1325 */
1326kern_return_t
9bccf70c
A
1327get_set_state(
1328 thread_act_t act,
1329 int flavor,
1330 thread_state_t state,
1331 int *pcount,
1332 void (*handler)(
1333 ReturnHandler *rh,
1334 thread_act_t act))
1c79356b 1335{
9bccf70c 1336 GetSetState gss;
1c79356b
A
1337
1338 /* Initialize a small parameter structure */
1339 gss.rh.handler = handler;
1340 gss.flavor = flavor;
1341 gss.state = state;
1342 gss.pcount = pcount;
1343 gss.result = KERN_ABORTED; /* iff wait below is interrupted */
1344
1345 /* Add it to the thr_act's return handler list */
9bccf70c
A
1346 gss.rh.next = act->handlers;
1347 act->handlers = &gss.rh;
1c79356b 1348
9bccf70c 1349 act_set_apc(act);
1c79356b 1350
9bccf70c
A
1351 assert(act->thread);
1352 assert(act != current_act());
1353
1c79356b 1354 for (;;) {
9bccf70c
A
1355 wait_result_t result;
1356
55e303ae 1357 if ( act->started &&
9bccf70c
A
1358 act->thread->top_act == act )
1359 thread_wakeup_one(&act->suspend_count);
1360
1c79356b
A
1361 /*
1362 * Wait must be interruptible to avoid deadlock (e.g.) with
1363 * task_suspend() when caller and target of get_set_state()
1364 * are in same task.
1365 */
9bccf70c
A
1366 result = assert_wait(&gss, THREAD_ABORTSAFE);
1367 act_unlock_thread(act);
1368
1369 if (result == THREAD_WAITING)
1370 result = thread_block(THREAD_CONTINUE_NULL);
1371
1372 assert(result != THREAD_WAITING);
1373
1374 if (gss.result != KERN_ABORTED) {
1375 assert(result != THREAD_INTERRUPTED);
1c79356b 1376 break;
9bccf70c
A
1377 }
1378
1379 /* JMM - What about other aborts (like BSD signals)? */
1c79356b
A
1380 if (current_act()->handlers)
1381 act_execute_returnhandlers();
9bccf70c
A
1382
1383 act_lock_thread(act);
1c79356b
A
1384 }
1385
9bccf70c 1386 return (gss.result);
1c79356b
A
1387}
1388
1389void
1390set_state_handler(ReturnHandler *rh, thread_act_t thr_act)
1391{
1392 GetSetState *gss = (GetSetState*)rh;
1393
55e303ae 1394 gss->result = machine_thread_set_state(thr_act, gss->flavor,
1c79356b
A
1395 gss->state, *gss->pcount);
1396 thread_wakeup((event_t)gss);
1397}
1398
1399void
1400get_state_handler(ReturnHandler *rh, thread_act_t thr_act)
1401{
1402 GetSetState *gss = (GetSetState*)rh;
1403
55e303ae 1404 gss->result = machine_thread_get_state(thr_act, gss->flavor,
1c79356b
A
1405 gss->state,
1406 (mach_msg_type_number_t *) gss->pcount);
1407 thread_wakeup((event_t)gss);
1408}
1409
1410kern_return_t
1411act_get_state_locked(thread_act_t thr_act, int flavor, thread_state_t state,
1412 mach_msg_type_number_t *pcount)
1413{
1c79356b
A
1414 return(get_set_state(thr_act, flavor, state, (int*)pcount, get_state_handler));
1415}
1416
1417kern_return_t
1418act_set_state_locked(thread_act_t thr_act, int flavor, thread_state_t state,
1419 mach_msg_type_number_t count)
1420{
1c79356b
A
1421 return(get_set_state(thr_act, flavor, state, (int*)&count, set_state_handler));
1422}
1423
1424kern_return_t
1425act_set_state(thread_act_t thr_act, int flavor, thread_state_t state,
1426 mach_msg_type_number_t count)
1427{
1428 if (thr_act == THR_ACT_NULL || thr_act == current_act())
1429 return(KERN_INVALID_ARGUMENT);
1430
1431 act_lock_thread(thr_act);
1432 return(act_set_state_locked(thr_act, flavor, state, count));
1433
1434}
1435
1436kern_return_t
1437act_get_state(thread_act_t thr_act, int flavor, thread_state_t state,
1438 mach_msg_type_number_t *pcount)
1439{
1440 if (thr_act == THR_ACT_NULL || thr_act == current_act())
1441 return(KERN_INVALID_ARGUMENT);
1442
1443 act_lock_thread(thr_act);
1444 return(act_get_state_locked(thr_act, flavor, state, pcount));
1445}
1446
1c79356b 1447void
9bccf70c
A
1448act_set_astbsd(
1449 thread_act_t act)
1c79356b 1450{
9bccf70c 1451 spl_t s = splsched();
0b4e3aa0 1452
9bccf70c
A
1453 if (act == current_act()) {
1454 thread_ast_set(act, AST_BSD);
1455 ast_propagate(act->ast);
1c79356b 1456 }
9bccf70c
A
1457 else {
1458 thread_t thread = act->thread;
1459 processor_t processor;
0b4e3aa0 1460
9bccf70c
A
1461 thread_lock(thread);
1462 thread_ast_set(act, AST_BSD);
1463 processor = thread->last_processor;
55e303ae
A
1464 if ( processor != PROCESSOR_NULL &&
1465 processor->state == PROCESSOR_RUNNING &&
1466 processor->active_thread == thread )
9bccf70c
A
1467 cause_ast_check(processor);
1468 thread_unlock(thread);
0b4e3aa0
A
1469 }
1470
9bccf70c 1471 splx(s);
1c79356b
A
1472}
1473
1474void
9bccf70c
A
1475act_set_apc(
1476 thread_act_t act)
1c79356b 1477{
9bccf70c
A
1478 spl_t s = splsched();
1479
1480 if (act == current_act()) {
1481 thread_ast_set(act, AST_APC);
1482 ast_propagate(act->ast);
1483 }
1484 else {
1485 thread_t thread = act->thread;
1486 processor_t processor;
1487
1488 thread_lock(thread);
1489 thread_ast_set(act, AST_APC);
1490 processor = thread->last_processor;
55e303ae
A
1491 if ( processor != PROCESSOR_NULL &&
1492 processor->state == PROCESSOR_RUNNING &&
1493 processor->active_thread == thread )
9bccf70c
A
1494 cause_ast_check(processor);
1495 thread_unlock(thread);
1496 }
1497
1498 splx(s);
1c79356b
A
1499}
1500
1501void
1502act_ulock_release_all(thread_act_t thr_act)
1503{
1504 ulock_t ulock;
1505
1506 while (!queue_empty(&thr_act->held_ulocks)) {
1507 ulock = (ulock_t) queue_first(&thr_act->held_ulocks);
1508 (void) lock_make_unstable(ulock, thr_act);
1509 (void) lock_release_internal(ulock, thr_act);
1510 }
1511}
1512
1513/*
1514 * Provide routines (for export to other components) of things that
1515 * are implemented as macros insternally.
1516 */
1c79356b
A
1517thread_act_t
1518thread_self(void)
1519{
1520 thread_act_t self = current_act_fast();
1521
1522 act_reference(self);
1523 return self;
1524}
1525
1526thread_act_t
1527mach_thread_self(void)
1528{
1529 thread_act_t self = current_act_fast();
1530
1531 act_reference(self);
1532 return self;
1533}