|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1994-1987 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: kern/thread.c
28: * Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub
29: * Date: 1986
30: *
31: * Thread management primitives implementation.
32: */
33:
34: #include <cpus.h>
35: #include <hw_footprint.h>
36: #include <mach_host.h>
37: #include <mach_fixpri.h>
38: #include <mach_pcsample.h>
39: #include <simple_clock.h>
40: #include <mach_debug.h>
41: #include <net_atm.h>
42:
43: #include <mach/std_types.h>
44: #include <mach/policy.h>
45: #include <mach/thread_info.h>
46: #include <mach/thread_special_ports.h>
47: #include <mach/thread_status.h>
48: #include <mach/time_value.h>
49: #include "vm_param.h"
50: #include <kern/ast.h>
51: #include <kern/counters.h>
52: #include <kern/ipc_tt.h>
53: #include <kern/mach_param.h>
54: #include <kern/processor.h>
55: #include <kern/queue.h>
56: #include <kern/sched.h>
57: #include <kern/sched_prim.h>
58: #include <kern/thread.h>
59: #include <kern/thread_swap.h>
60: #include <kern/host.h>
61: #include <kern/zalloc.h>
62: #include <vm/vm_kern.h>
63: #include <ipc/ipc_kmsg.h>
64: #include <ipc/ipc_port.h>
65: #include <ipc/mach_msg.h>
66: #include <machine/machspl.h> /* for splsched */
67: #include <machine/thread.h> /* for MACHINE_STACK */
68:
69: #if NET_ATM
70: #include <chips/nw_mk.h>
71: #endif
72:
73: thread_t active_threads[NCPUS];
74: vm_offset_t active_stacks[NCPUS];
75:
76: struct zone *thread_zone;
77:
78: queue_head_t reaper_queue;
79: decl_simple_lock_data(, reaper_lock)
80:
81: extern int tick;
82:
83: extern void pcb_module_init(void);
84:
85: /* private */
86: struct thread thread_template;
87:
88: #if MACH_DEBUG
89: void stack_init(vm_offset_t stack); /* forward */
90: void stack_finalize(vm_offset_t stack); /* forward */
91:
92: #define STACK_MARKER 0xdeadbeefU
93: boolean_t stack_check_usage = FALSE;
94: decl_simple_lock_data(, stack_usage_lock)
95: vm_size_t stack_max_usage = 0;
96: #endif /* MACH_DEBUG */
97:
98: /*
99: * Machine-dependent code must define:
100: * pcb_init
101: * pcb_terminate
102: * pcb_collect
103: *
104: * The thread->pcb field is reserved for machine-dependent code.
105: */
106:
107: #ifdef MACHINE_STACK
108: /*
109: * Machine-dependent code must define:
110: * stack_alloc_try
111: * stack_alloc
112: * stack_free
113: * stack_handoff
114: * stack_collect
115: * and if MACH_DEBUG:
116: * stack_statistics
117: */
118: #else /* MACHINE_STACK */
119: /*
120: * We allocate stacks from generic kernel VM.
121: * Machine-dependent code must define:
122: * stack_attach
123: * stack_detach
124: * stack_handoff
125: *
126: * The stack_free_list can only be accessed at splsched,
127: * because stack_alloc_try/thread_invoke operate at splsched.
128: */
129:
130: decl_simple_lock_data(, stack_lock_data)/* splsched only */
131: #define stack_lock() simple_lock(&stack_lock_data)
132: #define stack_unlock() simple_unlock(&stack_lock_data)
133:
134: vm_offset_t stack_free_list; /* splsched only */
135: unsigned int stack_free_count = 0; /* splsched only */
136: unsigned int stack_free_limit = 1; /* patchable */
137:
138: unsigned int stack_alloc_hits = 0; /* debugging */
139: unsigned int stack_alloc_misses = 0; /* debugging */
140: unsigned int stack_alloc_max = 0; /* debugging */
141:
142: /*
143: * The next field is at the base of the stack,
144: * so the low end is left unsullied.
145: */
146:
147: #define stack_next(stack) (*((vm_offset_t *)((stack) + KERNEL_STACK_SIZE) - 1))
148:
149: /*
150: * stack_alloc_try:
151: *
152: * Non-blocking attempt to allocate a kernel stack.
153: * Called at splsched with the thread locked.
154: */
155:
156: boolean_t stack_alloc_try(
157: thread_t thread,
158: void (*resume)(thread_t))
159: {
160: register vm_offset_t stack;
161:
162: stack_lock();
163: stack = stack_free_list;
164: if (stack != 0) {
165: stack_free_list = stack_next(stack);
166: stack_free_count--;
167: } else {
168: stack = thread->stack_privilege;
169: }
170: stack_unlock();
171:
172: if (stack != 0) {
173: stack_attach(thread, stack, resume);
174: stack_alloc_hits++;
175: return TRUE;
176: } else {
177: stack_alloc_misses++;
178: return FALSE;
179: }
180: }
181:
182: /*
183: * stack_alloc:
184: *
185: * Allocate a kernel stack for a thread.
186: * May block.
187: */
188:
189: void stack_alloc(
190: thread_t thread,
191: void (*resume)(thread_t))
192: {
193: vm_offset_t stack;
194: spl_t s;
195:
196: /*
197: * We first try the free list. It is probably empty,
198: * or stack_alloc_try would have succeeded, but possibly
199: * a stack was freed before the swapin thread got to us.
200: */
201:
202: s = splsched();
203: stack_lock();
204: stack = stack_free_list;
205: if (stack != 0) {
206: stack_free_list = stack_next(stack);
207: stack_free_count--;
208: }
209: stack_unlock();
210: (void) splx(s);
211:
212: if (stack == 0) {
213: /*
214: * Kernel stacks should be naturally aligned,
215: * so that it is easy to find the starting/ending
216: * addresses of a stack given an address in the middle.
217: */
218:
219: if (kmem_alloc_aligned(kernel_map, &stack, KERNEL_STACK_SIZE)
220: != KERN_SUCCESS)
221: panic("stack_alloc");
222:
223: #if MACH_DEBUG
224: stack_init(stack);
225: #endif /* MACH_DEBUG */
226: }
227:
228: stack_attach(thread, stack, resume);
229: }
230:
231: /*
232: * stack_free:
233: *
234: * Free a thread's kernel stack.
235: * Called at splsched with the thread locked.
236: */
237:
238: void stack_free(
239: thread_t thread)
240: {
241: register vm_offset_t stack;
242:
243: stack = stack_detach(thread);
244:
245: if (stack != thread->stack_privilege) {
246: stack_lock();
247: stack_next(stack) = stack_free_list;
248: stack_free_list = stack;
249: if (++stack_free_count > stack_alloc_max)
250: stack_alloc_max = stack_free_count;
251: stack_unlock();
252: }
253: }
254:
255: /*
256: * stack_collect:
257: *
258: * Free excess kernel stacks.
259: * May block.
260: */
261:
262: void stack_collect(void)
263: {
264: register vm_offset_t stack;
265: spl_t s;
266:
267: s = splsched();
268: stack_lock();
269: while (stack_free_count > stack_free_limit) {
270: stack = stack_free_list;
271: stack_free_list = stack_next(stack);
272: stack_free_count--;
273: stack_unlock();
274: (void) splx(s);
275:
276: #if MACH_DEBUG
277: stack_finalize(stack);
278: #endif /* MACH_DEBUG */
279: kmem_free(kernel_map, stack, KERNEL_STACK_SIZE);
280:
281: s = splsched();
282: stack_lock();
283: }
284: stack_unlock();
285: (void) splx(s);
286: }
287: #endif /* MACHINE_STACK */
288:
289: /*
290: * stack_privilege:
291: *
292: * stack_alloc_try on this thread must always succeed.
293: */
294:
295: void stack_privilege(
296: register thread_t thread)
297: {
298: /*
299: * This implementation only works for the current thread.
300: */
301:
302: if (thread != current_thread())
303: panic("stack_privilege");
304:
305: if (thread->stack_privilege == 0)
306: thread->stack_privilege = current_stack();
307: }
308:
309: void thread_init(void)
310: {
311: thread_zone = zinit(
312: sizeof(struct thread),
313: THREAD_MAX * sizeof(struct thread),
314: THREAD_CHUNK * sizeof(struct thread),
315: 0, "threads");
316:
317: /*
318: * Fill in a template thread for fast initialization.
319: * [Fields that must be (or are typically) reset at
320: * time of creation are so noted.]
321: */
322:
323: /* thread_template.links (none) */
324: thread_template.runq = RUN_QUEUE_NULL;
325:
326: /* thread_template.task (later) */
327: /* thread_template.thread_list (later) */
328: /* thread_template.pset_threads (later) */
329:
330: /* thread_template.lock (later) */
331: /* one ref for being alive; one for the guy who creates the thread */
332: thread_template.ref_count = 2;
333:
334: thread_template.pcb = (pcb_t) 0; /* (reset) */
335: thread_template.kernel_stack = (vm_offset_t) 0;
336: thread_template.stack_privilege = (vm_offset_t) 0;
337:
338: thread_template.wait_event = 0;
339: /* thread_template.suspend_count (later) */
340: thread_template.wait_result = KERN_SUCCESS;
341: thread_template.wake_active = FALSE;
342: thread_template.state = TH_SUSP | TH_SWAPPED;
343: thread_template.swap_func = thread_bootstrap_return;
344:
345: /* thread_template.priority (later) */
346: thread_template.max_priority = BASEPRI_USER;
347: /* thread_template.sched_pri (later - compute_priority) */
348: #if MACH_FIXPRI
349: thread_template.sched_data = 0;
350: thread_template.policy = POLICY_TIMESHARE;
351: #endif /* MACH_FIXPRI */
352: thread_template.depress_priority = -1;
353: thread_template.cpu_usage = 0;
354: thread_template.sched_usage = 0;
355: /* thread_template.sched_stamp (later) */
356:
357: thread_template.recover = (vm_offset_t) 0;
358: thread_template.vm_privilege = FALSE;
359:
360: thread_template.user_stop_count = 1;
361:
362: /* thread_template.<IPC structures> (later) */
363:
364: timer_init(&(thread_template.user_timer));
365: timer_init(&(thread_template.system_timer));
366: thread_template.user_timer_save.low = 0;
367: thread_template.user_timer_save.high = 0;
368: thread_template.system_timer_save.low = 0;
369: thread_template.system_timer_save.high = 0;
370: thread_template.cpu_delta = 0;
371: thread_template.sched_delta = 0;
372:
373: thread_template.active = FALSE; /* reset */
374: thread_template.ast = AST_ZILCH;
375:
376: /* thread_template.processor_set (later) */
377: thread_template.bound_processor = PROCESSOR_NULL;
378: #if MACH_HOST
379: thread_template.may_assign = TRUE;
380: thread_template.assign_active = FALSE;
381: #endif /* MACH_HOST */
382:
383: #if NCPUS > 1
384: /* thread_template.last_processor (later) */
385: #endif /* NCPUS > 1 */
386:
387: /*
388: * Initialize other data structures used in
389: * this module.
390: */
391:
392: queue_init(&reaper_queue);
393: simple_lock_init(&reaper_lock);
394:
395: #ifndef MACHINE_STACK
396: simple_lock_init(&stack_lock_data);
397: #endif /* MACHINE_STACK */
398:
399: #if MACH_DEBUG
400: simple_lock_init(&stack_usage_lock);
401: #endif /* MACH_DEBUG */
402:
403: /*
404: * Initialize any machine-dependent
405: * per-thread structures necessary.
406: */
407:
408: pcb_module_init();
409: }
410:
411: kern_return_t thread_create(
412: register task_t parent_task,
413: thread_t *child_thread) /* OUT */
414: {
415: register thread_t new_thread;
416: register processor_set_t pset;
417:
418: if (parent_task == TASK_NULL)
419: return KERN_INVALID_ARGUMENT;
420:
421: /*
422: * Allocate a thread and initialize static fields
423: */
424:
425: new_thread = (thread_t) zalloc(thread_zone);
426:
427: if (new_thread == THREAD_NULL)
428: return KERN_RESOURCE_SHORTAGE;
429:
430: *new_thread = thread_template;
431:
432: record_time_stamp (&new_thread->creation_time);
433:
434: /*
435: * Initialize runtime-dependent fields
436: */
437:
438: new_thread->task = parent_task;
439: simple_lock_init(&new_thread->lock);
440: new_thread->sched_stamp = sched_tick;
441: thread_timeout_setup(new_thread);
442:
443: /*
444: * Create a pcb. The kernel stack is created later,
445: * when the thread is swapped-in.
446: */
447: pcb_init(new_thread);
448:
449: ipc_thread_init(new_thread);
450:
451: #if NET_ATM
452: new_thread->nw_ep_waited = 0;
453: #endif
454:
455: /*
456: * Find the processor set for the parent task.
457: */
458: task_lock(parent_task);
459: pset = parent_task->processor_set;
460: pset_reference(pset);
461: task_unlock(parent_task);
462:
463: /*
464: * Lock both the processor set and the task,
465: * so that the thread can be added to both
466: * simultaneously. Processor set must be
467: * locked first.
468: */
469:
470: Restart:
471: pset_lock(pset);
472: task_lock(parent_task);
473:
474: /*
475: * If the task has changed processor sets,
476: * catch up (involves lots of lock juggling).
477: */
478: {
479: processor_set_t cur_pset;
480:
481: cur_pset = parent_task->processor_set;
482: if (!cur_pset->active)
483: cur_pset = &default_pset;
484:
485: if (cur_pset != pset) {
486: pset_reference(cur_pset);
487: task_unlock(parent_task);
488: pset_unlock(pset);
489: pset_deallocate(pset);
490: pset = cur_pset;
491: goto Restart;
492: }
493: }
494:
495: /*
496: * Set the thread`s priority from the pset and task.
497: */
498:
499: new_thread->priority = parent_task->priority;
500: if (pset->max_priority > new_thread->max_priority)
501: new_thread->max_priority = pset->max_priority;
502: if (new_thread->max_priority > new_thread->priority)
503: new_thread->priority = new_thread->max_priority;
504: /*
505: * Don't need to lock thread here because it can't
506: * possibly execute and no one else knows about it.
507: */
508: compute_priority(new_thread, TRUE);
509:
510: /*
511: * Thread is suspended if the task is. Add 1 to
512: * suspend count since thread is created in suspended
513: * state.
514: */
515: new_thread->suspend_count = parent_task->suspend_count + 1;
516:
517: /*
518: * Add the thread to the processor set.
519: * If the pset is empty, suspend the thread again.
520: */
521:
522: pset_add_thread(pset, new_thread);
523: if (pset->empty)
524: new_thread->suspend_count++;
525:
526: #if HW_FOOTPRINT
527: /*
528: * Need to set last_processor, idle processor would be best, but
529: * that requires extra locking nonsense. Go for tail of
530: * processors queue to avoid master.
531: */
532: if (!pset->empty) {
533: new_thread->last_processor =
534: (processor_t)queue_first(&pset->processors);
535: }
536: else {
537: /*
538: * Thread created in empty processor set. Pick
539: * master processor as an acceptable legal value.
540: */
541: new_thread->last_processor = master_processor;
542: }
543: #else /* HW_FOOTPRINT */
544: /*
545: * Don't need to initialize because the context switch
546: * code will set it before it can be used.
547: */
548: #endif /* HW_FOOTPRINT */
549:
550: #if MACH_PCSAMPLE
551: new_thread->pc_sample.buffer = 0;
552: new_thread->pc_sample.seqno = 0;
553: new_thread->pc_sample.sampletypes = 0;
554: #endif /* MACH_PCSAMPLE */
555:
556: new_thread->pc_sample.buffer = 0;
557: /*
558: * Add the thread to the task`s list of threads.
559: * The new thread holds another reference to the task.
560: */
561:
562: parent_task->ref_count++;
563:
564: parent_task->thread_count++;
565: queue_enter(&parent_task->thread_list, new_thread, thread_t,
566: thread_list);
567:
568: /*
569: * Finally, mark the thread active.
570: */
571:
572: new_thread->active = TRUE;
573:
574: if (!parent_task->active) {
575: task_unlock(parent_task);
576: pset_unlock(pset);
577: (void) thread_terminate(new_thread);
578: /* release ref we would have given our caller */
579: thread_deallocate(new_thread);
580: return KERN_FAILURE;
581: }
582: task_unlock(parent_task);
583: pset_unlock(pset);
584:
585: ipc_thread_enable(new_thread);
586:
587: *child_thread = new_thread;
588: return KERN_SUCCESS;
589: }
590:
591: unsigned int thread_deallocate_stack = 0;
592:
593: void thread_deallocate(
594: register thread_t thread)
595: {
596: spl_t s;
597: register task_t task;
598: register processor_set_t pset;
599:
600: time_value_t user_time, system_time;
601:
602: if (thread == THREAD_NULL)
603: return;
604:
605: /*
606: * First, check for new count > 0 (the common case).
607: * Only the thread needs to be locked.
608: */
609: s = splsched();
610: thread_lock(thread);
611: if (--thread->ref_count > 0) {
612: thread_unlock(thread);
613: (void) splx(s);
614: return;
615: }
616:
617: /*
618: * Count is zero. However, the task's and processor set's
619: * thread lists have implicit references to
620: * the thread, and may make new ones. Their locks also
621: * dominate the thread lock. To check for this, we
622: * temporarily restore the one thread reference, unlock
623: * the thread, and then lock the other structures in
624: * the proper order.
625: */
626: thread->ref_count = 1;
627: thread_unlock(thread);
628: (void) splx(s);
629:
630: pset = thread->processor_set;
631: pset_lock(pset);
632:
633: #if MACH_HOST
634: /*
635: * The thread might have moved.
636: */
637: while (pset != thread->processor_set) {
638: pset_unlock(pset);
639: pset = thread->processor_set;
640: pset_lock(pset);
641: }
642: #endif /* MACH_HOST */
643:
644: task = thread->task;
645: task_lock(task);
646:
647: s = splsched();
648: thread_lock(thread);
649:
650: if (--thread->ref_count > 0) {
651: /*
652: * Task or processor_set made extra reference.
653: */
654: thread_unlock(thread);
655: (void) splx(s);
656: task_unlock(task);
657: pset_unlock(pset);
658: return;
659: }
660:
661: /*
662: * Thread has no references - we can remove it.
663: */
664:
665: /*
666: * Remove pending timeouts.
667: */
668: reset_timeout_check(&thread->timer);
669:
670: reset_timeout_check(&thread->depress_timer);
671: thread->depress_priority = -1;
672:
673: /*
674: * Accumulate times for dead threads in task.
675: */
676: thread_read_times(thread, &user_time, &system_time);
677: time_value_add(&task->total_user_time, &user_time);
678: time_value_add(&task->total_system_time, &system_time);
679:
680: /*
681: * Remove thread from task list and processor_set threads list.
682: */
683: task->thread_count--;
684: queue_remove(&task->thread_list, thread, thread_t, thread_list);
685:
686: pset_remove_thread(pset, thread);
687:
688: thread_unlock(thread); /* no more references - safe */
689: (void) splx(s);
690: task_unlock(task);
691: pset_unlock(pset);
692: pset_deallocate(pset);
693:
694: /*
695: * A couple of quick sanity checks
696: */
697:
698: if (thread == current_thread()) {
699: panic("thread deallocating itself");
700: }
701: if ((thread->state & ~(TH_RUN | TH_HALTED | TH_SWAPPED)) != TH_SUSP)
702: panic("unstopped thread destroyed!");
703:
704: /*
705: * Deallocate the task reference, since we know the thread
706: * is not running.
707: */
708: task_deallocate(thread->task); /* may block */
709:
710: /*
711: * Clean up any machine-dependent resources.
712: */
713: if ((thread->state & TH_SWAPPED) == 0) {
714: spl_t _s_ = splsched();
715: stack_free(thread);
716: (void) splx(s);
717: thread_deallocate_stack++;
718: }
719: /*
720: * Rattle the event count machinery (gag)
721: */
722: evc_notify_abort(thread);
723:
724: pcb_terminate(thread);
725: zfree(thread_zone, (vm_offset_t) thread);
726: }
727:
728: void thread_reference(
729: register thread_t thread)
730: {
731: spl_t s;
732:
733: if (thread == THREAD_NULL)
734: return;
735:
736: s = splsched();
737: thread_lock(thread);
738: thread->ref_count++;
739: thread_unlock(thread);
740: (void) splx(s);
741: }
742:
743: /*
744: * thread_terminate:
745: *
746: * Permanently stop execution of the specified thread.
747: *
748: * A thread to be terminated must be allowed to clean up any state
749: * that it has before it exits. The thread is broken out of any
750: * wait condition that it is in, and signalled to exit. It then
751: * cleans up its state and calls thread_halt_self on its way out of
752: * the kernel. The caller waits for the thread to halt, terminates
753: * its IPC state, and then deallocates it.
754: *
755: * If the caller is the current thread, it must still exit the kernel
756: * to clean up any state (thread and port references, messages, etc).
757: * When it exits the kernel, it then terminates its IPC state and
758: * queues itself for the reaper thread, which will wait for the thread
759: * to stop and then deallocate it. (A thread cannot deallocate itself,
760: * since it needs a kernel stack to execute.)
761: */
762: kern_return_t thread_terminate(
763: register thread_t thread)
764: {
765: register thread_t cur_thread = current_thread();
766: register task_t cur_task;
767: spl_t s;
768:
769: if (thread == THREAD_NULL)
770: return KERN_INVALID_ARGUMENT;
771:
772: /*
773: * Break IPC control over the thread.
774: */
775: ipc_thread_disable(thread);
776:
777: if (thread == cur_thread) {
778:
779: /*
780: * Current thread will queue itself for reaper when
781: * exiting kernel.
782: */
783: s = splsched();
784: thread_lock(thread);
785: if (thread->active) {
786: thread->active = FALSE;
787: thread_ast_set(thread, AST_TERMINATE);
788: }
789: thread_unlock(thread);
790: ast_on(cpu_number(), AST_TERMINATE);
791: splx(s);
792: return KERN_SUCCESS;
793: }
794:
795: /*
796: * Lock both threads and the current task
797: * to check termination races and prevent deadlocks.
798: */
799: cur_task = current_task();
800: task_lock(cur_task);
801: s = splsched();
802: if ((vm_offset_t)thread < (vm_offset_t)cur_thread) {
803: thread_lock(thread);
804: thread_lock(cur_thread);
805: }
806: else {
807: thread_lock(cur_thread);
808: thread_lock(thread);
809: }
810:
811: /*
812: * If the current thread is being terminated, help out.
813: */
814: if ((!cur_task->active) || (!cur_thread->active)) {
815: thread_unlock(cur_thread);
816: thread_unlock(thread);
817: (void) splx(s);
818: task_unlock(cur_task);
819: thread_terminate(cur_thread);
820: return KERN_FAILURE;
821: }
822:
823: thread_unlock(cur_thread);
824: task_unlock(cur_task);
825:
826: /*
827: * Terminate victim thread.
828: */
829: if (!thread->active) {
830: /*
831: * Someone else got there first.
832: */
833: thread_unlock(thread);
834: (void) splx(s);
835: return KERN_FAILURE;
836: }
837:
838: thread->active = FALSE;
839:
840: thread_unlock(thread);
841: (void) splx(s);
842:
843: #if MACH_HOST
844: /*
845: * Reassign thread to default pset if needed.
846: */
847: thread_freeze(thread);
848: if (thread->processor_set != &default_pset) {
849: thread_doassign(thread, &default_pset, FALSE);
850: }
851: #endif /* MACH_HOST */
852:
853: /*
854: * Halt the victim at the clean point.
855: */
856: (void) thread_halt(thread, TRUE);
857: #if MACH_HOST
858: thread_unfreeze(thread);
859: #endif /* MACH_HOST */
860: /*
861: * Shut down the victims IPC and deallocate its
862: * reference to itself.
863: */
864: ipc_thread_terminate(thread);
865: #if NET_ATM
866: mk_waited_collect(thread);
867: #endif
868: thread_deallocate(thread);
869: return KERN_SUCCESS;
870: }
871:
872: /*
873: * thread_force_terminate:
874: *
875: * Version of thread_terminate called by task_terminate. thread is
876: * not the current thread. task_terminate is the dominant operation,
877: * so we can force this thread to stop.
878: */
879: void
880: thread_force_terminate(
881: register thread_t thread)
882: {
883: boolean_t deallocate_here = FALSE;
884: spl_t s;
885:
886: ipc_thread_disable(thread);
887:
888: #if MACH_HOST
889: /*
890: * Reassign thread to default pset if needed.
891: */
892: thread_freeze(thread);
893: if (thread->processor_set != &default_pset)
894: thread_doassign(thread, &default_pset, FALSE);
895: #endif /* MACH_HOST */
896:
897: s = splsched();
898: thread_lock(thread);
899: deallocate_here = thread->active;
900: thread->active = FALSE;
901: thread_unlock(thread);
902: (void) splx(s);
903:
904: (void) thread_halt(thread, TRUE);
905: ipc_thread_terminate(thread);
906: #if NET_ATM
907: mk_waited_collect(thread);
908: #endif
909:
910: #if MACH_HOST
911: thread_unfreeze(thread);
912: #endif /* MACH_HOST */
913:
914: if (deallocate_here)
915: thread_deallocate(thread);
916: }
917:
918:
919: /*
920: * Halt a thread at a clean point, leaving it suspended.
921: *
922: * must_halt indicates whether thread must halt.
923: *
924: */
925: kern_return_t thread_halt(
926: register thread_t thread,
927: boolean_t must_halt)
928: {
929: register thread_t cur_thread = current_thread();
930: register kern_return_t ret;
931: spl_t s;
932:
933: if (thread == cur_thread)
934: panic("thread_halt: trying to halt current thread.");
935: /*
936: * If must_halt is FALSE, then a check must be made for
937: * a cycle of halt operations.
938: */
939: if (!must_halt) {
940: /*
941: * Grab both thread locks.
942: */
943: s = splsched();
944: if ((vm_offset_t)thread < (vm_offset_t)cur_thread) {
945: thread_lock(thread);
946: thread_lock(cur_thread);
947: }
948: else {
949: thread_lock(cur_thread);
950: thread_lock(thread);
951: }
952:
953: /*
954: * If target thread is already halted, grab a hold
955: * on it and return.
956: */
957: if (thread->state & TH_HALTED) {
958: thread->suspend_count++;
959: thread_unlock(cur_thread);
960: thread_unlock(thread);
961: (void) splx(s);
962: return KERN_SUCCESS;
963: }
964:
965: /*
966: * If someone is trying to halt us, we have a potential
967: * halt cycle. Break the cycle by interrupting anyone
968: * who is trying to halt us, and causing this operation
969: * to fail; retry logic will only retry operations
970: * that cannot deadlock. (If must_halt is TRUE, this
971: * operation can never cause a deadlock.)
972: */
973: if (cur_thread->ast & AST_HALT) {
974: thread_wakeup_with_result((event_t)&cur_thread->wake_active,
975: THREAD_INTERRUPTED);
976: thread_unlock(thread);
977: thread_unlock(cur_thread);
978: (void) splx(s);
979: return KERN_FAILURE;
980: }
981:
982: thread_unlock(cur_thread);
983:
984: }
985: else {
986: /*
987: * Lock thread and check whether it is already halted.
988: */
989: s = splsched();
990: thread_lock(thread);
991: if (thread->state & TH_HALTED) {
992: thread->suspend_count++;
993: thread_unlock(thread);
994: (void) splx(s);
995: return KERN_SUCCESS;
996: }
997: }
998:
999: /*
1000: * Suspend thread - inline version of thread_hold() because
1001: * thread is already locked.
1002: */
1003: thread->suspend_count++;
1004: thread->state |= TH_SUSP;
1005:
1006: /*
1007: * If someone else is halting it, wait for that to complete.
1008: * Fail if wait interrupted and must_halt is false.
1009: */
1010: while ((thread->ast & AST_HALT) && (!(thread->state & TH_HALTED))) {
1011: thread->wake_active = TRUE;
1012: thread_sleep((event_t) &thread->wake_active,
1013: simple_lock_addr(thread->lock), TRUE);
1014:
1015: if (thread->state & TH_HALTED) {
1016: (void) splx(s);
1017: return KERN_SUCCESS;
1018: }
1019: if ((current_thread()->wait_result != THREAD_AWAKENED)
1020: && !(must_halt)) {
1021: (void) splx(s);
1022: thread_release(thread);
1023: return KERN_FAILURE;
1024: }
1025: thread_lock(thread);
1026: }
1027:
1028: /*
1029: * Otherwise, have to do it ourselves.
1030: */
1031:
1032: thread_ast_set(thread, AST_HALT);
1033:
1034: while (TRUE) {
1035: /*
1036: * Wait for thread to stop.
1037: */
1038: thread_unlock(thread);
1039: (void) splx(s);
1040:
1041: ret = thread_dowait(thread, must_halt);
1042:
1043: /*
1044: * If the dowait failed, so do we. Drop AST_HALT, and
1045: * wake up anyone else who might be waiting for it.
1046: */
1047: if (ret != KERN_SUCCESS) {
1048: s = splsched();
1049: thread_lock(thread);
1050: thread_ast_clear(thread, AST_HALT);
1051: thread_wakeup_with_result((event_t)&thread->wake_active,
1052: THREAD_INTERRUPTED);
1053: thread_unlock(thread);
1054: (void) splx(s);
1055:
1056: thread_release(thread);
1057: return ret;
1058: }
1059:
1060: /*
1061: * Clear any interruptible wait.
1062: */
1063: clear_wait(thread, THREAD_INTERRUPTED, TRUE);
1064:
1065: /*
1066: * If the thread's at a clean point, we're done.
1067: * Don't need a lock because it really is stopped.
1068: */
1069: if (thread->state & TH_HALTED) {
1070: return KERN_SUCCESS;
1071: }
1072:
1073: /*
1074: * If the thread is at a nice continuation,
1075: * or a continuation with a cleanup routine,
1076: * call the cleanup routine.
1077: */
1078: if ((((thread->swap_func == mach_msg_continue) ||
1079: (thread->swap_func == mach_msg_receive_continue)) &&
1080: mach_msg_interrupt(thread)) ||
1081: (thread->swap_func == thread_exception_return) ||
1082: (thread->swap_func == thread_bootstrap_return)) {
1083: s = splsched();
1084: thread_lock(thread);
1085: thread->state |= TH_HALTED;
1086: thread_ast_clear(thread, AST_HALT);
1087: thread_unlock(thread);
1088: splx(s);
1089:
1090: return KERN_SUCCESS;
1091: }
1092:
1093: /*
1094: * Force the thread to stop at a clean
1095: * point, and arrange to wait for it.
1096: *
1097: * Set it running, so it can notice. Override
1098: * the suspend count. We know that the thread
1099: * is suspended and not waiting.
1100: *
1101: * Since the thread may hit an interruptible wait
1102: * before it reaches a clean point, we must force it
1103: * to wake us up when it does so. This involves some
1104: * trickery:
1105: * We mark the thread SUSPENDED so that thread_block
1106: * will suspend it and wake us up.
1107: * We mark the thread RUNNING so that it will run.
1108: * We mark the thread UN-INTERRUPTIBLE (!) so that
1109: * some other thread trying to halt or suspend it won't
1110: * take it off the run queue before it runs. Since
1111: * dispatching a thread (the tail of thread_invoke) marks
1112: * the thread interruptible, it will stop at the next
1113: * context switch or interruptible wait.
1114: */
1115:
1116: s = splsched();
1117: thread_lock(thread);
1118: if ((thread->state & TH_SCHED_STATE) != TH_SUSP)
1119: panic("thread_halt");
1120: thread->state |= TH_RUN | TH_UNINT;
1121: thread_setrun(thread, FALSE);
1122:
1123: /*
1124: * Continue loop and wait for thread to stop.
1125: */
1126: }
1127: }
1128:
1129: void walking_zombie(void)
1130: {
1131: panic("the zombie walks!");
1132: }
1133:
1134: /*
1135: * Thread calls this routine on exit from the kernel when it
1136: * notices a halt request.
1137: */
1138: void thread_halt_self(void)
1139: {
1140: register thread_t thread = current_thread();
1141: spl_t s;
1142:
1143: if (thread->ast & AST_TERMINATE) {
1144: /*
1145: * Thread is terminating itself. Shut
1146: * down IPC, then queue it up for the
1147: * reaper thread.
1148: */
1149: ipc_thread_terminate(thread);
1150: #if NET_ATM
1151: mk_waited_collect(thread);
1152: #endif
1153:
1154: thread_hold(thread);
1155:
1156: s = splsched();
1157: simple_lock(&reaper_lock);
1158: enqueue_tail(&reaper_queue, (queue_entry_t) thread);
1159: simple_unlock(&reaper_lock);
1160:
1161: thread_lock(thread);
1162: thread->state |= TH_HALTED;
1163: thread_unlock(thread);
1164: (void) splx(s);
1165:
1166: thread_wakeup((event_t)&reaper_queue);
1167: counter(c_thread_halt_self_block++);
1168: thread_block(walking_zombie);
1169: /*NOTREACHED*/
1170: } else {
1171: /*
1172: * Thread was asked to halt - show that it
1173: * has done so.
1174: */
1175: s = splsched();
1176: thread_lock(thread);
1177: thread->state |= TH_HALTED;
1178: thread_ast_clear(thread, AST_HALT);
1179: thread_unlock(thread);
1180: splx(s);
1181: counter(c_thread_halt_self_block++);
1182: thread_block(thread_exception_return);
1183: /*
1184: * thread_release resets TH_HALTED.
1185: */
1186: }
1187: }
1188:
1189: /*
1190: * thread_hold:
1191: *
1192: * Suspend execution of the specified thread.
1193: * This is a recursive-style suspension of the thread, a count of
1194: * suspends is maintained.
1195: */
1196: void thread_hold(
1197: register thread_t thread)
1198: {
1199: spl_t s;
1200:
1201: s = splsched();
1202: thread_lock(thread);
1203: thread->suspend_count++;
1204: thread->state |= TH_SUSP;
1205: thread_unlock(thread);
1206: (void) splx(s);
1207: }
1208:
1209: /*
1210: * thread_dowait:
1211: *
1212: * Wait for a thread to actually enter stopped state.
1213: *
1214: * must_halt argument indicates if this may fail on interruption.
1215: * This is FALSE only if called from thread_abort via thread_halt.
1216: */
1217: kern_return_t
1218: thread_dowait(
1219: register thread_t thread,
1220: boolean_t must_halt)
1221: {
1222: register boolean_t need_wakeup;
1223: register kern_return_t ret = KERN_SUCCESS;
1224: spl_t s;
1225:
1226: if (thread == current_thread())
1227: panic("thread_dowait");
1228:
1229: /*
1230: * If a thread is not interruptible, it may not be suspended
1231: * until it becomes interruptible. In this case, we wait for
1232: * the thread to stop itself, and indicate that we are waiting
1233: * for it to stop so that it can wake us up when it does stop.
1234: *
1235: * If the thread is interruptible, we may be able to suspend
1236: * it immediately. There are several cases:
1237: *
1238: * 1) The thread is already stopped (trivial)
1239: * 2) The thread is runnable (marked RUN and on a run queue).
1240: * We pull it off the run queue and mark it stopped.
1241: * 3) The thread is running. We wait for it to stop.
1242: */
1243:
1244: need_wakeup = FALSE;
1245: s = splsched();
1246: thread_lock(thread);
1247:
1248: for (;;) {
1249: switch (thread->state & TH_SCHED_STATE) {
1250: case TH_SUSP:
1251: case TH_WAIT | TH_SUSP:
1252: /*
1253: * Thread is already suspended, or sleeping in an
1254: * interruptible wait. We win!
1255: */
1256: break;
1257:
1258: case TH_RUN | TH_SUSP:
1259: /*
1260: * The thread is interruptible. If we can pull
1261: * it off a runq, stop it here.
1262: */
1263: if (rem_runq(thread) != RUN_QUEUE_NULL) {
1264: thread->state &= ~TH_RUN;
1265: need_wakeup = thread->wake_active;
1266: thread->wake_active = FALSE;
1267: break;
1268: }
1269: #if NCPUS > 1
1270: /*
1271: * The thread must be running, so make its
1272: * processor execute ast_check(). This
1273: * should cause the thread to take an ast and
1274: * context switch to suspend for us.
1275: */
1276: cause_ast_check(thread->last_processor);
1277: #endif /* NCPUS > 1 */
1278:
1279: /*
1280: * Fall through to wait for thread to stop.
1281: */
1282:
1283: case TH_RUN | TH_SUSP | TH_UNINT:
1284: case TH_RUN | TH_WAIT | TH_SUSP:
1285: case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
1286: case TH_WAIT | TH_SUSP | TH_UNINT:
1287: /*
1288: * Wait for the thread to stop, or sleep interruptibly
1289: * (thread_block will stop it in the latter case).
1290: * Check for failure if interrupted.
1291: */
1292: thread->wake_active = TRUE;
1293: thread_sleep((event_t) &thread->wake_active,
1294: simple_lock_addr(thread->lock), TRUE);
1295: thread_lock(thread);
1296: if ((current_thread()->wait_result != THREAD_AWAKENED) &&
1297: !must_halt) {
1298: ret = KERN_FAILURE;
1299: break;
1300: }
1301:
1302: /*
1303: * Repeat loop to check thread`s state.
1304: */
1305: continue;
1306: }
1307: /*
1308: * Thread is stopped at this point.
1309: */
1310: break;
1311: }
1312:
1313: thread_unlock(thread);
1314: (void) splx(s);
1315:
1316: if (need_wakeup)
1317: thread_wakeup((event_t) &thread->wake_active);
1318:
1319: return ret;
1320: }
1321:
1322: void thread_release(
1323: register thread_t thread)
1324: {
1325: spl_t s;
1326:
1327: s = splsched();
1328: thread_lock(thread);
1329: if (--thread->suspend_count == 0) {
1330: thread->state &= ~(TH_SUSP | TH_HALTED);
1331: if ((thread->state & (TH_WAIT | TH_RUN)) == 0) {
1332: /* was only suspended */
1333: thread->state |= TH_RUN;
1334: thread_setrun(thread, TRUE);
1335: }
1336: }
1337: thread_unlock(thread);
1338: (void) splx(s);
1339: }
1340:
1341: kern_return_t thread_suspend(
1342: register thread_t thread)
1343: {
1344: register boolean_t hold;
1345: spl_t spl;
1346:
1347: if (thread == THREAD_NULL)
1348: return KERN_INVALID_ARGUMENT;
1349:
1350: hold = FALSE;
1351: spl = splsched();
1352: thread_lock(thread);
1353: if (thread->user_stop_count++ == 0) {
1354: hold = TRUE;
1355: thread->suspend_count++;
1356: thread->state |= TH_SUSP;
1357: }
1358: thread_unlock(thread);
1359: (void) splx(spl);
1360:
1361: /*
1362: * Now wait for the thread if necessary.
1363: */
1364: if (hold) {
1365: if (thread == current_thread()) {
1366: /*
1367: * We want to call thread_block on our way out,
1368: * to stop running.
1369: */
1370: spl = splsched();
1371: ast_on(cpu_number(), AST_BLOCK);
1372: (void) splx(spl);
1373: } else
1374: (void) thread_dowait(thread, TRUE);
1375: }
1376: return KERN_SUCCESS;
1377: }
1378:
1379:
1380: kern_return_t thread_resume(
1381: register thread_t thread)
1382: {
1383: register kern_return_t ret;
1384: spl_t s;
1385:
1386: if (thread == THREAD_NULL)
1387: return KERN_INVALID_ARGUMENT;
1388:
1389: ret = KERN_SUCCESS;
1390:
1391: s = splsched();
1392: thread_lock(thread);
1393: if (thread->user_stop_count > 0) {
1394: if (--thread->user_stop_count == 0) {
1395: if (--thread->suspend_count == 0) {
1396: thread->state &= ~(TH_SUSP | TH_HALTED);
1397: if ((thread->state & (TH_WAIT | TH_RUN)) == 0) {
1398: /* was only suspended */
1399: thread->state |= TH_RUN;
1400: thread_setrun(thread, TRUE);
1401: }
1402: }
1403: }
1404: }
1405: else {
1406: ret = KERN_FAILURE;
1407: }
1408:
1409: thread_unlock(thread);
1410: (void) splx(s);
1411:
1412: return ret;
1413: }
1414:
1415: /*
1416: * Return thread's machine-dependent state.
1417: */
1418: kern_return_t thread_get_state(
1419: register thread_t thread,
1420: int flavor,
1421: thread_state_t old_state, /* pointer to OUT array */
1422: natural_t *old_state_count) /*IN/OUT*/
1423: {
1424: kern_return_t ret;
1425:
1426: if (thread == THREAD_NULL || thread == current_thread()) {
1427: return KERN_INVALID_ARGUMENT;
1428: }
1429:
1430: thread_hold(thread);
1431: (void) thread_dowait(thread, TRUE);
1432:
1433: ret = thread_getstatus(thread, flavor, old_state, old_state_count);
1434:
1435: thread_release(thread);
1436: return ret;
1437: }
1438:
1439: /*
1440: * Change thread's machine-dependent state.
1441: */
1442: kern_return_t thread_set_state(
1443: register thread_t thread,
1444: int flavor,
1445: thread_state_t new_state,
1446: natural_t new_state_count)
1447: {
1448: kern_return_t ret;
1449:
1450: if (thread == THREAD_NULL || thread == current_thread()) {
1451: return KERN_INVALID_ARGUMENT;
1452: }
1453:
1454: thread_hold(thread);
1455: (void) thread_dowait(thread, TRUE);
1456:
1457: ret = thread_setstatus(thread, flavor, new_state, new_state_count);
1458:
1459: thread_release(thread);
1460: return ret;
1461: }
1462:
1463: kern_return_t thread_info(
1464: register thread_t thread,
1465: int flavor,
1466: thread_info_t thread_info_out, /* pointer to OUT array */
1467: natural_t *thread_info_count) /*IN/OUT*/
1468: {
1469: int state, flags;
1470: spl_t s;
1471:
1472: if (thread == THREAD_NULL)
1473: return KERN_INVALID_ARGUMENT;
1474:
1475: if (flavor == THREAD_BASIC_INFO) {
1476: register thread_basic_info_t basic_info;
1477:
1478: /* Allow *thread_info_count to be one smaller than the
1479: usual amount, because creation_time is a new member
1480: that some callers might not know about. */
1481:
1482: if (*thread_info_count < THREAD_BASIC_INFO_COUNT - 1) {
1483: return KERN_INVALID_ARGUMENT;
1484: }
1485:
1486: basic_info = (thread_basic_info_t) thread_info_out;
1487:
1488: s = splsched();
1489: thread_lock(thread);
1490:
1491: /*
1492: * Update lazy-evaluated scheduler info because someone wants it.
1493: */
1494: if ((thread->state & TH_RUN) == 0 &&
1495: thread->sched_stamp != sched_tick)
1496: update_priority(thread);
1497:
1498: /* fill in info */
1499:
1500: thread_read_times(thread,
1501: &basic_info->user_time,
1502: &basic_info->system_time);
1503: basic_info->base_priority = thread->priority;
1504: basic_info->cur_priority = thread->sched_pri;
1505: basic_info->creation_time = thread->creation_time;
1506:
1507: /*
1508: * To calculate cpu_usage, first correct for timer rate,
1509: * then for 5/8 ageing. The correction factor [3/5] is
1510: * (1/(5/8) - 1).
1511: */
1512: basic_info->cpu_usage = thread->cpu_usage /
1513: (TIMER_RATE/TH_USAGE_SCALE);
1514: basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5;
1515: #if SIMPLE_CLOCK
1516: /*
1517: * Clock drift compensation.
1518: */
1519: basic_info->cpu_usage =
1520: (basic_info->cpu_usage * 1000000)/sched_usec;
1521: #endif /* SIMPLE_CLOCK */
1522:
1523: flags = 0;
1524: if (thread->state & TH_SWAPPED)
1525: flags |= TH_FLAGS_SWAPPED;
1526: if (thread->state & TH_IDLE)
1527: flags |= TH_FLAGS_IDLE;
1528:
1529: if (thread->state & TH_HALTED)
1530: state = TH_STATE_HALTED;
1531: else
1532: if (thread->state & TH_RUN)
1533: state = TH_STATE_RUNNING;
1534: else
1535: if (thread->state & TH_UNINT)
1536: state = TH_STATE_UNINTERRUPTIBLE;
1537: else
1538: if (thread->state & TH_SUSP)
1539: state = TH_STATE_STOPPED;
1540: else
1541: if (thread->state & TH_WAIT)
1542: state = TH_STATE_WAITING;
1543: else
1544: state = 0; /* ? */
1545:
1546: basic_info->run_state = state;
1547: basic_info->flags = flags;
1548: basic_info->suspend_count = thread->user_stop_count;
1549: if (state == TH_STATE_RUNNING)
1550: basic_info->sleep_time = 0;
1551: else
1552: basic_info->sleep_time = sched_tick - thread->sched_stamp;
1553:
1554: thread_unlock(thread);
1555: splx(s);
1556:
1557: if (*thread_info_count > THREAD_BASIC_INFO_COUNT)
1558: *thread_info_count = THREAD_BASIC_INFO_COUNT;
1559: return KERN_SUCCESS;
1560: }
1561: else if (flavor == THREAD_SCHED_INFO) {
1562: register thread_sched_info_t sched_info;
1563:
1564: if (*thread_info_count < THREAD_SCHED_INFO_COUNT) {
1565: return KERN_INVALID_ARGUMENT;
1566: }
1567:
1568: sched_info = (thread_sched_info_t) thread_info_out;
1569:
1570: s = splsched();
1571: thread_lock(thread);
1572:
1573: #if MACH_FIXPRI
1574: sched_info->policy = thread->policy;
1575: if (thread->policy == POLICY_FIXEDPRI) {
1576: sched_info->data = (thread->sched_data * tick)/1000;
1577: }
1578: else {
1579: sched_info->data = 0;
1580: }
1581: #else /* MACH_FIXPRI */
1582: sched_info->policy = POLICY_TIMESHARE;
1583: sched_info->data = 0;
1584: #endif /* MACH_FIXPRI */
1585:
1586: sched_info->base_priority = thread->priority;
1587: sched_info->max_priority = thread->max_priority;
1588: sched_info->cur_priority = thread->sched_pri;
1589:
1590: sched_info->depressed = (thread->depress_priority >= 0);
1591: sched_info->depress_priority = thread->depress_priority;
1592:
1593: thread_unlock(thread);
1594: splx(s);
1595:
1596: *thread_info_count = THREAD_SCHED_INFO_COUNT;
1597: return KERN_SUCCESS;
1598: }
1599:
1600: return KERN_INVALID_ARGUMENT;
1601: }
1602:
1603: kern_return_t thread_abort(
1604: register thread_t thread)
1605: {
1606: if (thread == THREAD_NULL || thread == current_thread()) {
1607: return KERN_INVALID_ARGUMENT;
1608: }
1609:
1610: /*
1611: *
1612: * clear it of an event wait
1613: */
1614: evc_notify_abort(thread);
1615:
1616: /*
1617: * Try to force the thread to a clean point
1618: * If the halt operation fails return KERN_ABORTED.
1619: * ipc code will convert this to an ipc interrupted error code.
1620: */
1621: if (thread_halt(thread, FALSE) != KERN_SUCCESS)
1622: return KERN_ABORTED;
1623:
1624: /*
1625: * If the thread was in an exception, abort that too.
1626: */
1627: mach_msg_abort_rpc(thread);
1628:
1629: /*
1630: * Then set it going again.
1631: */
1632: thread_release(thread);
1633:
1634: /*
1635: * Also abort any depression.
1636: */
1637: if (thread->depress_priority != -1)
1638: thread_depress_abort(thread);
1639:
1640: return KERN_SUCCESS;
1641: }
1642:
1643: /*
1644: * thread_start:
1645: *
1646: * Start a thread at the specified routine.
1647: * The thread must be in a swapped state.
1648: */
1649:
1650: void
1651: thread_start(
1652: thread_t thread,
1653: continuation_t start)
1654: {
1655: thread->swap_func = start;
1656: }
1657:
1658: /*
1659: * kernel_thread:
1660: *
1661: * Start up a kernel thread in the specified task.
1662: */
1663:
1664: thread_t kernel_thread(
1665: task_t task,
1666: continuation_t start,
1667: void * arg)
1668: {
1669: thread_t thread;
1670:
1671: (void) thread_create(task, &thread);
1672: /* release "extra" ref that thread_create gave us */
1673: thread_deallocate(thread);
1674: thread_start(thread, start);
1675: thread->ith_other = arg;
1676:
1677: /*
1678: * We ensure that the kernel thread starts with a stack.
1679: * The swapin mechanism might not be operational yet.
1680: */
1681: thread_doswapin(thread);
1682: thread->max_priority = BASEPRI_SYSTEM;
1683: thread->priority = BASEPRI_SYSTEM;
1684: thread->sched_pri = BASEPRI_SYSTEM;
1685: (void) thread_resume(thread);
1686: return thread;
1687: }
1688:
1689: /*
1690: * reaper_thread:
1691: *
1692: * This kernel thread runs forever looking for threads to destroy
1693: * (when they request that they be destroyed, of course).
1694: */
1695: void reaper_thread_continue(void)
1696: {
1697: for (;;) {
1698: register thread_t thread;
1699: spl_t s;
1700:
1701: s = splsched();
1702: simple_lock(&reaper_lock);
1703:
1704: while ((thread = (thread_t) dequeue_head(&reaper_queue))
1705: != THREAD_NULL) {
1706: simple_unlock(&reaper_lock);
1707: (void) splx(s);
1708:
1709: (void) thread_dowait(thread, TRUE); /* may block */
1710: thread_deallocate(thread); /* may block */
1711:
1712: s = splsched();
1713: simple_lock(&reaper_lock);
1714: }
1715:
1716: assert_wait((event_t) &reaper_queue, FALSE);
1717: simple_unlock(&reaper_lock);
1718: (void) splx(s);
1719: counter(c_reaper_thread_block++);
1720: thread_block(reaper_thread_continue);
1721: }
1722: }
1723:
1724: void reaper_thread(void)
1725: {
1726: reaper_thread_continue();
1727: /*NOTREACHED*/
1728: }
1729:
1730: #if MACH_HOST
1731: /*
1732: * thread_assign:
1733: *
1734: * Change processor set assignment.
1735: * Caller must hold an extra reference to the thread (if this is
1736: * called directly from the ipc interface, this is an operation
1737: * in progress reference). Caller must hold no locks -- this may block.
1738: */
1739:
1740: kern_return_t
1741: thread_assign(
1742: thread_t thread,
1743: processor_set_t new_pset)
1744: {
1745: if (thread == THREAD_NULL || new_pset == PROCESSOR_SET_NULL) {
1746: return KERN_INVALID_ARGUMENT;
1747: }
1748:
1749: thread_freeze(thread);
1750: thread_doassign(thread, new_pset, TRUE);
1751:
1752: return KERN_SUCCESS;
1753: }
1754:
1755: /*
1756: * thread_freeze:
1757: *
1758: * Freeze thread's assignment. Prelude to assigning thread.
1759: * Only one freeze may be held per thread.
1760: */
1761: void
1762: thread_freeze(
1763: thread_t thread)
1764: {
1765: spl_t s;
1766: /*
1767: * Freeze the assignment, deferring to a prior freeze.
1768: */
1769: s = splsched();
1770: thread_lock(thread);
1771: while (thread->may_assign == FALSE) {
1772: thread->assign_active = TRUE;
1773: thread_sleep((event_t) &thread->assign_active,
1774: simple_lock_addr(thread->lock), FALSE);
1775: thread_lock(thread);
1776: }
1777: thread->may_assign = FALSE;
1778: thread_unlock(thread);
1779: (void) splx(s);
1780:
1781: }
1782:
1783: /*
1784: * thread_unfreeze: release freeze on thread's assignment.
1785: */
1786: void
1787: thread_unfreeze(
1788: thread_t thread)
1789: {
1790: spl_t s;
1791:
1792: s = splsched();
1793: thread_lock(thread);
1794: thread->may_assign = TRUE;
1795: if (thread->assign_active) {
1796: thread->assign_active = FALSE;
1797: thread_wakeup((event_t)&thread->assign_active);
1798: }
1799: thread_unlock(thread);
1800: splx(s);
1801: }
1802:
1803: /*
1804: * thread_doassign:
1805: *
1806: * Actually do thread assignment. thread_will_assign must have been
1807: * called on the thread. release_freeze argument indicates whether
1808: * to release freeze on thread.
1809: */
1810:
1811: void
1812: thread_doassign(
1813: register thread_t thread,
1814: register processor_set_t new_pset,
1815: boolean_t release_freeze)
1816: {
1817: register processor_set_t pset;
1818: register boolean_t old_empty, new_empty;
1819: boolean_t recompute_pri = FALSE;
1820: spl_t s;
1821:
1822: /*
1823: * Check for silly no-op.
1824: */
1825: pset = thread->processor_set;
1826: if (pset == new_pset) {
1827: if (release_freeze)
1828: thread_unfreeze(thread);
1829: return;
1830: }
1831: /*
1832: * Suspend the thread and stop it if it's not the current thread.
1833: */
1834: thread_hold(thread);
1835: if (thread != current_thread())
1836: (void) thread_dowait(thread, TRUE);
1837:
1838: /*
1839: * Lock both psets now, use ordering to avoid deadlocks.
1840: */
1841: Restart:
1842: if ((vm_offset_t)pset < (vm_offset_t)new_pset) {
1843: pset_lock(pset);
1844: pset_lock(new_pset);
1845: }
1846: else {
1847: pset_lock(new_pset);
1848: pset_lock(pset);
1849: }
1850:
1851: /*
1852: * Check if new_pset is ok to assign to. If not, reassign
1853: * to default_pset.
1854: */
1855: if (!new_pset->active) {
1856: pset_unlock(pset);
1857: pset_unlock(new_pset);
1858: new_pset = &default_pset;
1859: goto Restart;
1860: }
1861:
1862: pset_reference(new_pset);
1863:
1864: /*
1865: * Grab the thread lock and move the thread.
1866: * Then drop the lock on the old pset and the thread's
1867: * reference to it.
1868: */
1869: s = splsched();
1870: thread_lock(thread);
1871:
1872: thread_change_psets(thread, pset, new_pset);
1873:
1874: old_empty = pset->empty;
1875: new_empty = new_pset->empty;
1876:
1877: pset_unlock(pset);
1878:
1879: /*
1880: * Reset policy and priorities if needed.
1881: */
1882: #if MACH_FIXPRI
1883: if (thread->policy & new_pset->policies == 0) {
1884: thread->policy = POLICY_TIMESHARE;
1885: recompute_pri = TRUE;
1886: }
1887: #endif /* MACH_FIXPRI */
1888:
1889: if (thread->max_priority < new_pset->max_priority) {
1890: thread->max_priority = new_pset->max_priority;
1891: if (thread->priority < thread->max_priority) {
1892: thread->priority = thread->max_priority;
1893: recompute_pri = TRUE;
1894: }
1895: else {
1896: if ((thread->depress_priority >= 0) &&
1897: (thread->depress_priority < thread->max_priority)) {
1898: thread->depress_priority = thread->max_priority;
1899: }
1900: }
1901: }
1902:
1903: pset_unlock(new_pset);
1904:
1905: if (recompute_pri)
1906: compute_priority(thread, TRUE);
1907:
1908: if (release_freeze) {
1909: thread->may_assign = TRUE;
1910: if (thread->assign_active) {
1911: thread->assign_active = FALSE;
1912: thread_wakeup((event_t)&thread->assign_active);
1913: }
1914: }
1915:
1916: thread_unlock(thread);
1917: splx(s);
1918:
1919: pset_deallocate(pset);
1920:
1921: /*
1922: * Figure out hold status of thread. Threads assigned to empty
1923: * psets must be held. Therefore:
1924: * If old pset was empty release its hold.
1925: * Release our hold from above unless new pset is empty.
1926: */
1927:
1928: if (old_empty)
1929: thread_release(thread);
1930: if (!new_empty)
1931: thread_release(thread);
1932:
1933: /*
1934: * If current_thread is assigned, context switch to force
1935: * assignment to happen. This also causes hold to take
1936: * effect if the new pset is empty.
1937: */
1938: if (thread == current_thread()) {
1939: s = splsched();
1940: ast_on(cpu_number(), AST_BLOCK);
1941: (void) splx(s);
1942: }
1943: }
1944: #else /* MACH_HOST */
1945: kern_return_t
1946: thread_assign(
1947: thread_t thread,
1948: processor_set_t new_pset)
1949: {
1950: return KERN_FAILURE;
1951: }
1952: #endif /* MACH_HOST */
1953:
1954: /*
1955: * thread_assign_default:
1956: *
1957: * Special version of thread_assign for assigning threads to default
1958: * processor set.
1959: */
1960: kern_return_t
1961: thread_assign_default(
1962: thread_t thread)
1963: {
1964: return thread_assign(thread, &default_pset);
1965: }
1966:
1967: /*
1968: * thread_get_assignment
1969: *
1970: * Return current assignment for this thread.
1971: */
1972: kern_return_t thread_get_assignment(
1973: thread_t thread,
1974: processor_set_t *pset)
1975: {
1976: *pset = thread->processor_set;
1977: pset_reference(*pset);
1978: return KERN_SUCCESS;
1979: }
1980:
1981: /*
1982: * thread_priority:
1983: *
1984: * Set priority (and possibly max priority) for thread.
1985: */
1986: kern_return_t
1987: thread_priority(
1988: thread_t thread,
1989: int priority,
1990: boolean_t set_max)
1991: {
1992: spl_t s;
1993: kern_return_t ret = KERN_SUCCESS;
1994:
1995: if ((thread == THREAD_NULL) || invalid_pri(priority))
1996: return KERN_INVALID_ARGUMENT;
1997:
1998: s = splsched();
1999: thread_lock(thread);
2000:
2001: /*
2002: * Check for violation of max priority
2003: */
2004: if (priority < thread->max_priority) {
2005: ret = KERN_FAILURE;
2006: }
2007: else {
2008: /*
2009: * Set priorities. If a depression is in progress,
2010: * change the priority to restore.
2011: */
2012: if (thread->depress_priority >= 0) {
2013: thread->depress_priority = priority;
2014: }
2015: else {
2016: thread->priority = priority;
2017: compute_priority(thread, TRUE);
2018: }
2019:
2020: if (set_max)
2021: thread->max_priority = priority;
2022: }
2023: thread_unlock(thread);
2024: (void) splx(s);
2025:
2026: return ret;
2027: }
2028:
2029: /*
2030: * thread_set_own_priority:
2031: *
2032: * Internal use only; sets the priority of the calling thread.
2033: * Will adjust max_priority if necessary.
2034: */
2035: void
2036: thread_set_own_priority(
2037: int priority)
2038: {
2039: spl_t s;
2040: thread_t thread = current_thread();
2041:
2042: s = splsched();
2043: thread_lock(thread);
2044:
2045: if (priority < thread->max_priority)
2046: thread->max_priority = priority;
2047: thread->priority = priority;
2048: compute_priority(thread, TRUE);
2049:
2050: thread_unlock(thread);
2051: (void) splx(s);
2052: }
2053:
2054: /*
2055: * thread_max_priority:
2056: *
2057: * Reset the max priority for a thread.
2058: */
2059: kern_return_t
2060: thread_max_priority(
2061: thread_t thread,
2062: processor_set_t pset,
2063: int max_priority)
2064: {
2065: spl_t s;
2066: kern_return_t ret = KERN_SUCCESS;
2067:
2068: if ((thread == THREAD_NULL) || (pset == PROCESSOR_SET_NULL) ||
2069: invalid_pri(max_priority))
2070: return KERN_INVALID_ARGUMENT;
2071:
2072: s = splsched();
2073: thread_lock(thread);
2074:
2075: #if MACH_HOST
2076: /*
2077: * Check for wrong processor set.
2078: */
2079: if (pset != thread->processor_set) {
2080: ret = KERN_FAILURE;
2081: }
2082: else {
2083: #endif /* MACH_HOST */
2084: thread->max_priority = max_priority;
2085:
2086: /*
2087: * Reset priority if it violates new max priority
2088: */
2089: if (max_priority > thread->priority) {
2090: thread->priority = max_priority;
2091:
2092: compute_priority(thread, TRUE);
2093: }
2094: else {
2095: if (thread->depress_priority >= 0 &&
2096: max_priority > thread->depress_priority)
2097: thread->depress_priority = max_priority;
2098: }
2099: #if MACH_HOST
2100: }
2101: #endif /* MACH_HOST */
2102:
2103: thread_unlock(thread);
2104: (void) splx(s);
2105:
2106: return ret;
2107: }
2108:
2109: /*
2110: * thread_policy:
2111: *
2112: * Set scheduling policy for thread.
2113: */
2114: kern_return_t
2115: thread_policy(
2116: thread_t thread,
2117: int policy,
2118: int data)
2119: {
2120: #if MACH_FIXPRI
2121: register kern_return_t ret = KERN_SUCCESS;
2122: register int temp;
2123: spl_t s;
2124: #endif /* MACH_FIXPRI */
2125:
2126: if ((thread == THREAD_NULL) || invalid_policy(policy))
2127: return KERN_INVALID_ARGUMENT;
2128:
2129: #if MACH_FIXPRI
2130: s = splsched();
2131: thread_lock(thread);
2132:
2133: /*
2134: * Check if changing policy.
2135: */
2136: if (policy == thread->policy) {
2137: /*
2138: * Just changing data. This is meaningless for
2139: * timesharing, quantum for fixed priority (but
2140: * has no effect until current quantum runs out).
2141: */
2142: if (policy == POLICY_FIXEDPRI) {
2143: temp = data * 1000;
2144: if (temp % tick)
2145: temp += tick;
2146: thread->sched_data = temp/tick;
2147: }
2148: }
2149: else {
2150: /*
2151: * Changing policy. Check if new policy is allowed.
2152: */
2153: if ((thread->processor_set->policies & policy) == 0) {
2154: ret = KERN_FAILURE;
2155: }
2156: else {
2157: /*
2158: * Changing policy. Save data and calculate new
2159: * priority.
2160: */
2161: thread->policy = policy;
2162: if (policy == POLICY_FIXEDPRI) {
2163: temp = data * 1000;
2164: if (temp % tick)
2165: temp += tick;
2166: thread->sched_data = temp/tick;
2167: }
2168: compute_priority(thread, TRUE);
2169: }
2170: }
2171: thread_unlock(thread);
2172: (void) splx(s);
2173:
2174: return ret;
2175: #else /* MACH_FIXPRI */
2176: if (policy == POLICY_TIMESHARE)
2177: return KERN_SUCCESS;
2178: else
2179: return KERN_FAILURE;
2180: #endif /* MACH_FIXPRI */
2181: }
2182:
2183: /*
2184: * thread_wire:
2185: *
2186: * Specify that the target thread must always be able
2187: * to run and to allocate memory.
2188: */
2189: kern_return_t
2190: thread_wire(
2191: host_t host,
2192: thread_t thread,
2193: boolean_t wired)
2194: {
2195: spl_t s;
2196:
2197: if (host == HOST_NULL)
2198: return KERN_INVALID_ARGUMENT;
2199:
2200: if (thread == THREAD_NULL)
2201: return KERN_INVALID_ARGUMENT;
2202:
2203: /*
2204: * This implementation only works for the current thread.
2205: * See stack_privilege.
2206: */
2207: if (thread != current_thread())
2208: return KERN_INVALID_ARGUMENT;
2209:
2210: s = splsched();
2211: thread_lock(thread);
2212:
2213: if (wired) {
2214: thread->vm_privilege = TRUE;
2215: stack_privilege(thread);
2216: }
2217: else {
2218: thread->vm_privilege = FALSE;
2219: /*XXX stack_unprivilege(thread); */
2220: thread->stack_privilege = 0;
2221: }
2222:
2223: thread_unlock(thread);
2224: splx(s);
2225:
2226: return KERN_SUCCESS;
2227: }
2228:
2229: /*
2230: * thread_collect_scan:
2231: *
2232: * Attempt to free resources owned by threads.
2233: * pcb_collect doesn't do anything yet.
2234: */
2235:
2236: void thread_collect_scan(void)
2237: {
2238: #if 0
2239: register thread_t thread, prev_thread;
2240: processor_set_t pset, prev_pset;
2241:
2242: prev_thread = THREAD_NULL;
2243: prev_pset = PROCESSOR_SET_NULL;
2244:
2245: simple_lock(&all_psets_lock);
2246: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
2247: pset_lock(pset);
2248: queue_iterate(&pset->threads, thread, thread_t, pset_threads) {
2249: spl_t s = splsched();
2250: thread_lock(thread);
2251:
2252: /*
2253: * Only collect threads which are
2254: * not runnable and are swapped.
2255: */
2256:
2257: if ((thread->state & (TH_RUN|TH_SWAPPED))
2258: == TH_SWAPPED) {
2259: thread->ref_count++;
2260: thread_unlock(thread);
2261: (void) splx(s);
2262: pset->ref_count++;
2263: pset_unlock(pset);
2264: simple_unlock(&all_psets_lock);
2265:
2266: pcb_collect(thread);
2267:
2268: if (prev_thread != THREAD_NULL)
2269: thread_deallocate(prev_thread);
2270: prev_thread = thread;
2271:
2272: if (prev_pset != PROCESSOR_SET_NULL)
2273: pset_deallocate(prev_pset);
2274: prev_pset = pset;
2275:
2276: simple_lock(&all_psets_lock);
2277: pset_lock(pset);
2278: } else {
2279: thread_unlock(thread);
2280: (void) splx(s);
2281: }
2282: }
2283: pset_unlock(pset);
2284: }
2285: simple_unlock(&all_psets_lock);
2286:
2287: if (prev_thread != THREAD_NULL)
2288: thread_deallocate(prev_thread);
2289: if (prev_pset != PROCESSOR_SET_NULL)
2290: pset_deallocate(prev_pset);
2291: #endif /* 0 */
2292: }
2293:
2294: boolean_t thread_collect_allowed = TRUE;
2295: unsigned thread_collect_last_tick = 0;
2296: unsigned thread_collect_max_rate = 0; /* in ticks */
2297:
2298: /*
2299: * consider_thread_collect:
2300: *
2301: * Called by the pageout daemon when the system needs more free pages.
2302: */
2303:
2304: void consider_thread_collect(void)
2305: {
2306: /*
2307: * By default, don't attempt thread collection more frequently
2308: * than once a second.
2309: */
2310:
2311: if (thread_collect_max_rate == 0)
2312: thread_collect_max_rate = hz;
2313:
2314: if (thread_collect_allowed &&
2315: (sched_tick >
2316: (thread_collect_last_tick + thread_collect_max_rate))) {
2317: thread_collect_last_tick = sched_tick;
2318: thread_collect_scan();
2319: }
2320: }
2321:
2322: #if MACH_DEBUG
2323:
2324: vm_size_t stack_usage(
2325: register vm_offset_t stack)
2326: {
2327: int i;
2328:
2329: for (i = 0; i < KERNEL_STACK_SIZE/sizeof(unsigned int); i++)
2330: if (((unsigned int *)stack)[i] != STACK_MARKER)
2331: break;
2332:
2333: return KERNEL_STACK_SIZE - i * sizeof(unsigned int);
2334: }
2335:
2336: /*
2337: * Machine-dependent code should call stack_init
2338: * before doing its own initialization of the stack.
2339: */
2340:
2341: void stack_init(
2342: register vm_offset_t stack)
2343: {
2344: if (stack_check_usage) {
2345: int i;
2346:
2347: for (i = 0; i < KERNEL_STACK_SIZE/sizeof(unsigned int); i++)
2348: ((unsigned int *)stack)[i] = STACK_MARKER;
2349: }
2350: }
2351:
2352: /*
2353: * Machine-dependent code should call stack_finalize
2354: * before releasing the stack memory.
2355: */
2356:
2357: void stack_finalize(
2358: register vm_offset_t stack)
2359: {
2360: if (stack_check_usage) {
2361: vm_size_t used = stack_usage(stack);
2362:
2363: simple_lock(&stack_usage_lock);
2364: if (used > stack_max_usage)
2365: stack_max_usage = used;
2366: simple_unlock(&stack_usage_lock);
2367: }
2368: }
2369:
2370: #ifndef MACHINE_STACK
2371: /*
2372: * stack_statistics:
2373: *
2374: * Return statistics on cached kernel stacks.
2375: * *maxusagep must be initialized by the caller.
2376: */
2377:
2378: void stack_statistics(
2379: natural_t *totalp,
2380: vm_size_t *maxusagep)
2381: {
2382: spl_t s;
2383:
2384: s = splsched();
2385: stack_lock();
2386: if (stack_check_usage) {
2387: vm_offset_t stack;
2388:
2389: /*
2390: * This is pretty expensive to do at splsched,
2391: * but it only happens when someone makes
2392: * a debugging call, so it should be OK.
2393: */
2394:
2395: for (stack = stack_free_list; stack != 0;
2396: stack = stack_next(stack)) {
2397: vm_size_t usage = stack_usage(stack);
2398:
2399: if (usage > *maxusagep)
2400: *maxusagep = usage;
2401: }
2402: }
2403:
2404: *totalp = stack_free_count;
2405: stack_unlock();
2406: (void) splx(s);
2407: }
2408: #endif /* MACHINE_STACK */
2409:
2410: kern_return_t host_stack_usage(
2411: host_t host,
2412: vm_size_t *reservedp,
2413: unsigned int *totalp,
2414: vm_size_t *spacep,
2415: vm_size_t *residentp,
2416: vm_size_t *maxusagep,
2417: vm_offset_t *maxstackp)
2418: {
2419: unsigned int total;
2420: vm_size_t maxusage;
2421:
2422: if (host == HOST_NULL)
2423: return KERN_INVALID_HOST;
2424:
2425: simple_lock(&stack_usage_lock);
2426: maxusage = stack_max_usage;
2427: simple_unlock(&stack_usage_lock);
2428:
2429: stack_statistics(&total, &maxusage);
2430:
2431: *reservedp = 0;
2432: *totalp = total;
2433: *spacep = *residentp = total * round_page(KERNEL_STACK_SIZE);
2434: *maxusagep = maxusage;
2435: *maxstackp = 0;
2436: return KERN_SUCCESS;
2437: }
2438:
2439: kern_return_t processor_set_stack_usage(
2440: processor_set_t pset,
2441: unsigned int *totalp,
2442: vm_size_t *spacep,
2443: vm_size_t *residentp,
2444: vm_size_t *maxusagep,
2445: vm_offset_t *maxstackp)
2446: {
2447: unsigned int total;
2448: vm_size_t maxusage;
2449: vm_offset_t maxstack;
2450:
2451: register thread_t *threads;
2452: register thread_t tmp_thread;
2453:
2454: unsigned int actual; /* this many things */
2455: unsigned int i;
2456:
2457: vm_size_t size, size_needed;
2458: vm_offset_t addr;
2459:
2460: if (pset == PROCESSOR_SET_NULL)
2461: return KERN_INVALID_ARGUMENT;
2462:
2463: size = 0; addr = 0;
2464:
2465: for (;;) {
2466: pset_lock(pset);
2467: if (!pset->active) {
2468: pset_unlock(pset);
2469: return KERN_INVALID_ARGUMENT;
2470: }
2471:
2472: actual = pset->thread_count;
2473:
2474: /* do we have the memory we need? */
2475:
2476: size_needed = actual * sizeof(thread_t);
2477: if (size_needed <= size)
2478: break;
2479:
2480: /* unlock the pset and allocate more memory */
2481: pset_unlock(pset);
2482:
2483: if (size != 0)
2484: kfree(addr, size);
2485:
2486: assert(size_needed > 0);
2487: size = size_needed;
2488:
2489: addr = kalloc(size);
2490: if (addr == 0)
2491: return KERN_RESOURCE_SHORTAGE;
2492: }
2493:
2494: /* OK, have memory and the processor_set is locked & active */
2495:
2496: threads = (thread_t *) addr;
2497: for (i = 0, tmp_thread = (thread_t) queue_first(&pset->threads);
2498: i < actual;
2499: i++,
2500: tmp_thread = (thread_t) queue_next(&tmp_thread->pset_threads)) {
2501: thread_reference(tmp_thread);
2502: threads[i] = tmp_thread;
2503: }
2504: assert(queue_end(&pset->threads, (queue_entry_t) tmp_thread));
2505:
2506: /* can unlock processor set now that we have the thread refs */
2507: pset_unlock(pset);
2508:
2509: /* calculate maxusage and free thread references */
2510:
2511: total = 0;
2512: maxusage = 0;
2513: maxstack = 0;
2514: for (i = 0; i < actual; i++) {
2515: thread_t thread = threads[i];
2516: vm_offset_t stack = 0;
2517:
2518: /*
2519: * thread->kernel_stack is only accurate if the
2520: * thread isn't swapped and is not executing.
2521: *
2522: * Of course, we don't have the appropriate locks
2523: * for these shenanigans.
2524: */
2525:
2526: if ((thread->state & TH_SWAPPED) == 0) {
2527: int cpu;
2528:
2529: stack = thread->kernel_stack;
2530:
2531: for (cpu = 0; cpu < NCPUS; cpu++)
2532: if (active_threads[cpu] == thread) {
2533: stack = active_stacks[cpu];
2534: break;
2535: }
2536: }
2537:
2538: if (stack != 0) {
2539: total++;
2540:
2541: if (stack_check_usage) {
2542: vm_size_t usage = stack_usage(stack);
2543:
2544: if (usage > maxusage) {
2545: maxusage = usage;
2546: maxstack = (vm_offset_t) thread;
2547: }
2548: }
2549: }
2550:
2551: thread_deallocate(thread);
2552: }
2553:
2554: if (size != 0)
2555: kfree(addr, size);
2556:
2557: *totalp = total;
2558: *residentp = *spacep = total * round_page(KERNEL_STACK_SIZE);
2559: *maxusagep = maxusage;
2560: *maxstackp = maxstack;
2561: return KERN_SUCCESS;
2562: }
2563:
2564: /*
2565: * Useful in the debugger:
2566: */
2567: void
2568: thread_stats(void)
2569: {
2570: register thread_t thread;
2571: int total = 0, rpcreply = 0;
2572:
2573: queue_iterate(&default_pset.threads, thread, thread_t, pset_threads) {
2574: total++;
2575: if (thread->ith_rpc_reply != IP_NULL)
2576: rpcreply++;
2577: }
2578:
2579: printf("%d total threads.\n", total);
2580: printf("%d using rpc_reply.\n", rpcreply);
2581: }
2582: #endif /* MACH_DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.