1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include <mach/mach_types.h>
47#include <mach/kern_return.h>
48#include <mach/alert.h>
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>
55#include <kern/mach_param.h>
56#include <kern/zalloc.h>
57#include <kern/thread.h>
58#include <kern/task.h>
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>
70#include <kern/processor.h>
71#include <kern/timer.h>
72#include <mach_prof.h>
73#include <mach/rpc.h>
74
75void act_abort(thread_t);
76void act_set_apc(thread_t);
77void install_special_handler_locked(thread_t);
78void special_handler_continue(void);
79
80
81
82
83
84kern_return_t
85thread_terminate_internal(
86 thread_t thread)
87{
88 kern_return_t result = KERN_SUCCESS;
89
90 thread_mtx_lock(thread);
91
92 if (thread->active) {
93 thread->active = FALSE;
94
95 act_abort(thread);
96
97 if (thread->started)
98 clear_wait(thread, THREAD_INTERRUPTED);
99 else {
100 clear_wait(thread, THREAD_AWAKENED);
101 thread->started = TRUE;
102 }
103 }
104 else
105 result = KERN_TERMINATED;
106
107 thread_mtx_unlock(thread);
108
109 if (thread != current_thread() && result == KERN_SUCCESS)
110 thread_wait(thread);
111
112 return (result);
113}
114
115
116
117
118kern_return_t
119thread_terminate(
120 thread_t thread)
121{
122 kern_return_t result;
123
124 if (thread == THREAD_NULL)
125 return (KERN_INVALID_ARGUMENT);
126
127 if ( thread->task == kernel_task &&
128 thread != current_thread() )
129 return (KERN_FAILURE);
130
131 result = thread_terminate_internal(thread);
132
133
134
135
136
137
138
139 if (thread->task == kernel_task) {
140 ml_set_interrupts_enabled(FALSE);
141 ast_taken(AST_APC, TRUE);
142 panic("thread_terminate");
143 }
144
145 return (result);
146}
147
148
149
150
151
152
153
154
155void
156thread_hold(
157 register thread_t thread)
158{
159 if (thread->suspend_count++ == 0) {
160 install_special_handler(thread);
161 if (thread->started)
162 thread_wakeup_one(&thread->suspend_count);
163 }
164}
165
166
167
168
169
170
171
172void
173thread_release(
174 register thread_t thread)
175{
176 if ( thread->suspend_count > 0 &&
177 --thread->suspend_count == 0 ) {
178 if (thread->started)
179 thread_wakeup_one(&thread->suspend_count);
180 else {
181 clear_wait(thread, THREAD_AWAKENED);
182 thread->started = TRUE;
183 }
184 }
185}
186
187kern_return_t
188thread_suspend(
189 register thread_t thread)
190{
191 thread_t self = current_thread();
192 kern_return_t result = KERN_SUCCESS;
193
194 if (thread == THREAD_NULL || thread->task == kernel_task)
195 return (KERN_INVALID_ARGUMENT);
196
197 thread_mtx_lock(thread);
198
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);
205 }
206 }
207 else
208 result = KERN_TERMINATED;
209
210 thread_mtx_unlock(thread);
211
212 if (thread != self && result == KERN_SUCCESS)
213 thread_wait(thread);
214
215 return (result);
216}
217
218kern_return_t
219thread_resume(
220 register thread_t thread)
221{
222 kern_return_t result = KERN_SUCCESS;
223
224 if (thread == THREAD_NULL || thread->task == kernel_task)
225 return (KERN_INVALID_ARGUMENT);
226
227 thread_mtx_lock(thread);
228
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 {
236 clear_wait(thread, THREAD_AWAKENED);
237 thread->started = TRUE;
238 }
239 }
240 }
241 else
242 result = KERN_FAILURE;
243 }
244 else
245 result = KERN_TERMINATED;
246
247 thread_mtx_unlock(thread);
248
249 return (result);
250}
251
252
253
254
255
256
257kern_return_t
258thread_depress_abort(
259 register thread_t thread)
260{
261 kern_return_t result;
262
263 if (thread == THREAD_NULL)
264 return (KERN_INVALID_ARGUMENT);
265
266 thread_mtx_lock(thread);
267
268 if (thread->active)
269 result = thread_depress_abort_internal(thread);
270 else
271 result = KERN_TERMINATED;
272
273 thread_mtx_unlock(thread);
274
275 return (result);
276}
277
278
279
280
281
282
283
284
285void
286act_abort(
287 thread_t thread)
288{
289 spl_t s = splsched();
290
291 thread_lock(thread);
292
293 if (!(thread->state & TH_ABORT)) {
294 thread->state |= TH_ABORT;
295 install_special_handler_locked(thread);
296 }
297 else
298 thread->state &= ~TH_ABORT_SAFELY;
299
300 thread_unlock(thread);
301 splx(s);
302}
303
304kern_return_t
305thread_abort(
306 register thread_t thread)
307{
308 kern_return_t result = KERN_SUCCESS;
309
310 if (thread == THREAD_NULL)
311 return (KERN_INVALID_ARGUMENT);
312
313 thread_mtx_lock(thread);
314
315 if (thread->active) {
316 act_abort(thread);
317 clear_wait(thread, THREAD_INTERRUPTED);
318 }
319 else
320 result = KERN_TERMINATED;
321
322 thread_mtx_unlock(thread);
323
324 return (result);
325}
326
327kern_return_t
328thread_abort_safely(
329 thread_t thread)
330{
331 kern_return_t result = KERN_SUCCESS;
332
333 if (thread == THREAD_NULL)
334 return (KERN_INVALID_ARGUMENT);
335
336 thread_mtx_lock(thread);
337
338 if (thread->active) {
339 spl_t s = splsched();
340
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 }
348 }
349 thread_unlock(thread);
350 splx(s);
351 }
352 else
353 result = KERN_TERMINATED;
354
355 thread_mtx_unlock(thread);
356
357 return (result);
358}
359
360
361#include <mach/thread_info.h>
362#include <mach/thread_special_ports.h>
363#include <ipc/ipc_port.h>
364
365kern_return_t
366thread_info(
367 thread_t thread,
368 thread_flavor_t flavor,
369 thread_info_t thread_info_out,
370 mach_msg_type_number_t *thread_info_count)
371{
372 kern_return_t result;
373
374 if (thread == THREAD_NULL)
375 return (KERN_INVALID_ARGUMENT);
376
377 thread_mtx_lock(thread);
378
379 if (thread->active)
380 result = thread_info_internal(
381 thread, flavor, thread_info_out, thread_info_count);
382 else
383 result = KERN_TERMINATED;
384
385 thread_mtx_unlock(thread);
386
387 return (result);
388}
389
390kern_return_t
391thread_get_state(
392 register thread_t thread,
393 int flavor,
394 thread_state_t state,
395 mach_msg_type_number_t *state_count)
396{
397 kern_return_t result = KERN_SUCCESS;
398
399 if (thread == THREAD_NULL)
400 return (KERN_INVALID_ARGUMENT);
401
402 thread_mtx_lock(thread);
403
404 if (thread->active) {
405 if (thread != current_thread()) {
406 thread_hold(thread);
407
408 thread_mtx_unlock(thread);
409
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 }
420
421 thread_release(thread);
422 }
423 else
424 result = machine_thread_get_state(
425 thread, flavor, state, state_count);
426 }
427 else
428 result = KERN_TERMINATED;
429
430 thread_mtx_unlock(thread);
431
432 return (result);
433}
434
435
436
437
438
439kern_return_t
440thread_set_state(
441 register thread_t thread,
442 int flavor,
443 thread_state_t state,
444 mach_msg_type_number_t state_count)
445{
446 kern_return_t result = KERN_SUCCESS;
447
448 if (thread == THREAD_NULL)
449 return (KERN_INVALID_ARGUMENT);
450
451 thread_mtx_lock(thread);
452
453 if (thread->active) {
454 if (thread != current_thread()) {
455 thread_hold(thread);
456
457 thread_mtx_unlock(thread);
458
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 }
469
470 thread_release(thread);
471 }
472 else
473 result = machine_thread_set_state(
474 thread, flavor, state, state_count);
475 }
476 else
477 result = KERN_TERMINATED;
478
479 thread_mtx_unlock(thread);
480
481 return (result);
482}
483
484
485
486
487
488
489
490
491
492kern_return_t
493thread_state_initialize(
494 register thread_t thread)
495{
496 kern_return_t result = KERN_SUCCESS;
497
498 if (thread == THREAD_NULL)
499 return (KERN_INVALID_ARGUMENT);
500
501 thread_mtx_lock(thread);
502
503 if (thread->active) {
504 if (thread != current_thread()) {
505 thread_hold(thread);
506
507 thread_mtx_unlock(thread);
508
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 }
518
519 thread_release(thread);
520 }
521 else
522 result = machine_thread_state_initialize( thread );
523 }
524 else
525 result = KERN_TERMINATED;
526
527 thread_mtx_unlock(thread);
528
529 return (result);
530}
531
532
533kern_return_t
534thread_dup(
535 register thread_t target)
536{
537 thread_t self = current_thread();
538 kern_return_t result = KERN_SUCCESS;
539
540 if (target == THREAD_NULL || target == self)
541 return (KERN_INVALID_ARGUMENT);
542
543 thread_mtx_lock(target);
544
545 if (target->active) {
546 thread_hold(target);
547
548 thread_mtx_unlock(target);
549
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);
557 result = KERN_ABORTED;
558 }
559
560 thread_release(target);
561 }
562 else
563 result = KERN_TERMINATED;
564
565 thread_mtx_unlock(target);
566
567 return (result);
568}
569
570
571
572
573
574
575
576
577kern_return_t
578thread_setstatus(
579 register thread_t thread,
580 int flavor,
581 thread_state_t tstate,
582 mach_msg_type_number_t count)
583{
584
585 return (thread_set_state(thread, flavor, tstate, count));
586}
587
588
589
590
591
592
593kern_return_t
594thread_getstatus(
595 register thread_t thread,
596 int flavor,
597 thread_state_t tstate,
598 mach_msg_type_number_t *count)
599{
600 return (thread_get_state(thread, flavor, tstate, count));
601}
602
603
604
605
606
607
608
609
610
611void
612install_special_handler(
613 thread_t thread)
614{
615 spl_t s = splsched();
616
617 thread_lock(thread);
618 install_special_handler_locked(thread);
619 thread_unlock(thread);
620 splx(s);
621}
622
623
624
625
626
627
628
629
630void
631install_special_handler_locked(
632 thread_t thread)
633{
634 ReturnHandler **rh;
635
636
637
638 for (rh = &thread->handlers; *rh; rh = &(*rh)->next)
639 continue;
640
641 if (rh != &thread->special_handler.next)
642 *rh = &thread->special_handler;
643
644
645
646
647
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);
656 else {
657 processor_t processor = thread->last_processor;
658
659 if ( processor != PROCESSOR_NULL &&
660 processor->state == PROCESSOR_RUNNING &&
661 processor->active_thread == thread )
662 cause_ast_check(processor);
663 }
664}
665
666
667
668
669
670void
671act_execute_returnhandlers(void)
672{
673 thread_t thread = current_thread();
674
675 thread_ast_clear(thread, AST_APC);
676 spllo();
677
678 for (;;) {
679 ReturnHandler *rh;
680
681 thread_mtx_lock(thread);
682
683 (void)splsched();
684 thread_lock(thread);
685
686 rh = thread->handlers;
687 if (rh != NULL) {
688 thread->handlers = rh->next;
689
690 thread_unlock(thread);
691 spllo();
692
693 thread_mtx_unlock(thread);
694
695
696 (*rh->handler)(rh, thread);
697 }
698 else
699 break;
700 }
701
702 thread_unlock(thread);
703 spllo();
704
705 thread_mtx_unlock(thread);
706}
707
708
709
710
711
712
713
714
715
716
717void
718special_handler_continue(void)
719{
720 thread_t thread = current_thread();
721
722 thread_mtx_lock(thread);
723
724 if (thread->suspend_count > 0)
725 install_special_handler(thread);
726 else {
727 spl_t s = splsched();
728
729 thread_lock(thread);
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;
736 }
737 thread_unlock(thread);
738 splx(s);
739 }
740
741 thread_mtx_unlock(thread);
742
743 thread_exception_return();
744
745}
746
747
748
749
750
751void
752special_handler(
753 __unused ReturnHandler *rh,
754 thread_t thread)
755{
756 spl_t s;
757
758 thread_mtx_lock(thread);
759
760 s = splsched();
761 thread_lock(thread);
762 thread->state &= ~(TH_ABORT|TH_ABORT_SAFELY);
763 thread_unlock(thread);
764 splx(s);
765
766
767
768
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
776 }
777
778 thread_mtx_unlock(thread);
779
780 special_handler_continue();
781
782 }
783 }
784 else {
785 thread_mtx_unlock(thread);
786
787 thread_terminate_self();
788
789 }
790
791 thread_mtx_unlock(thread);
792}
793
794kern_return_t
795act_set_state(
796 thread_t thread,
797 int flavor,
798 thread_state_t state,
799 mach_msg_type_number_t count)
800{
801 if (thread == current_thread())
802 return (KERN_INVALID_ARGUMENT);
803
804 return (thread_set_state(thread, flavor, state, count));
805
806}
807
808kern_return_t
809act_get_state(
810 thread_t thread,
811 int flavor,
812 thread_state_t state,
813 mach_msg_type_number_t *count)
814{
815 if (thread == current_thread())
816 return (KERN_INVALID_ARGUMENT);
817
818 return (thread_get_state(thread, flavor, state, count));
819}
820
821void
822act_set_astbsd(
823 thread_t thread)
824{
825 spl_t s = splsched();
826
827 if (thread == current_thread()) {
828 thread_ast_set(thread, AST_BSD);
829 ast_propagate(thread->ast);
830 }
831 else {
832 processor_t processor;
833
834 thread_lock(thread);
835 thread_ast_set(thread, AST_BSD);
836 processor = thread->last_processor;
837 if ( processor != PROCESSOR_NULL &&
838 processor->state == PROCESSOR_RUNNING &&
839 processor->active_thread == thread )
840 cause_ast_check(processor);
841 thread_unlock(thread);
842 }
843
844 splx(s);
845}
846
847void
848act_set_apc(
849 thread_t thread)
850{
851 spl_t s = splsched();
852
853 if (thread == current_thread()) {
854 thread_ast_set(thread, AST_APC);
855 ast_propagate(thread->ast);
856 }
857 else {
858 processor_t processor;
859
860 thread_lock(thread);
861 thread_ast_set(thread, AST_APC);
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