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