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