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