-/*
- * Return info on stack usage for threads in a specific processor set
- */
-kern_return_t
-processor_set_stack_usage(
- processor_set_t pset,
- unsigned int *totalp,
- vm_size_t *spacep,
- vm_size_t *residentp,
- vm_size_t *maxusagep,
- vm_offset_t *maxstackp)
-{
-#if !MACH_DEBUG
- return KERN_NOT_SUPPORTED;
-#else
- unsigned int total;
- vm_size_t maxusage;
- vm_offset_t maxstack;
-
- register thread_t *threads;
- register thread_t thread;
-
- unsigned int actual; /* this many things */
- unsigned int i;
-
- vm_size_t size, size_needed;
- vm_offset_t addr;
-
- if (pset == PROCESSOR_SET_NULL)
- return KERN_INVALID_ARGUMENT;
-
- size = 0; addr = 0;
-
- for (;;) {
- pset_lock(pset);
- if (!pset->active) {
- pset_unlock(pset);
- return KERN_INVALID_ARGUMENT;
- }
-
- actual = pset->thread_count;
-
- /* do we have the memory we need? */
-
- size_needed = actual * sizeof(thread_t);
- if (size_needed <= size)
- break;
-
- /* unlock the pset and allocate more memory */
- pset_unlock(pset);
-
- if (size != 0)
- kfree(addr, size);
-
- assert(size_needed > 0);
- size = size_needed;
-
- addr = kalloc(size);
- if (addr == 0)
- return KERN_RESOURCE_SHORTAGE;
- }
-
- /* OK, have memory and the processor_set is locked & active */
-
- threads = (thread_t *) addr;
- for (i = 0, thread = (thread_t) queue_first(&pset->threads);
- i < actual;
- i++,
- thread = (thread_t) queue_next(&thread->pset_threads)) {
- thread_reference(thread);
- threads[i] = thread;
- }
- assert(queue_end(&pset->threads, (queue_entry_t) thread));
-
- /* can unlock processor set now that we have the thread refs */
- pset_unlock(pset);
-
- /* calculate maxusage and free thread references */
-
- total = 0;
- maxusage = 0;
- maxstack = 0;
- for (i = 0; i < actual; i++) {
- int cpu;
- thread_t thread = threads[i];
- vm_offset_t stack = 0;
-
- /*
- * thread->kernel_stack is only accurate if the
- * thread isn't swapped and is not executing.
- *
- * Of course, we don't have the appropriate locks
- * for these shenanigans.
- */
-
- stack = thread->kernel_stack;
-
- for (cpu = 0; cpu < NCPUS; cpu++)
- if (cpu_data[cpu].active_thread == thread) {
- stack = active_stacks[cpu];
- break;
- }
-
- if (stack != 0) {
- total++;
-
- if (stack_check_usage) {
- vm_size_t usage = stack_usage(stack);
-
- if (usage > maxusage) {
- maxusage = usage;
- maxstack = (vm_offset_t) thread;
- }
- }
- }
-
- thread_deallocate(thread);
- }
-
- if (size != 0)
- kfree(addr, size);
-
- *totalp = total;
- *residentp = *spacep = total * round_page(KERNEL_STACK_SIZE);
- *maxusagep = maxusage;
- *maxstackp = maxstack;
- return KERN_SUCCESS;
-
-#endif /* MACH_DEBUG */
-}