aboutsummaryrefslogtreecommitdiffstats
path: root/adv_cmds/ps/tasks.c
diff options
context:
space:
mode:
Diffstat (limited to 'adv_cmds/ps/tasks.c')
-rw-r--r--adv_cmds/ps/tasks.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/adv_cmds/ps/tasks.c b/adv_cmds/ps/tasks.c
new file mode 100644
index 0000000..4548b56
--- /dev/null
+++ b/adv_cmds/ps/tasks.c
@@ -0,0 +1,246 @@
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <locale.h>
+#include <pwd.h>
+
+#include "ps.h"
+#include <mach/shared_memory_server.h>
+
+extern kern_return_t task_for_pid(task_port_t task, pid_t pid, task_port_t *target);
+
+#define STATE_MAX 7
+
+int
+mach_state_order(s, sleep_time)
+int s;
+long sleep_time;
+{
+switch (s) {
+case TH_STATE_RUNNING: return(1);
+case TH_STATE_UNINTERRUPTIBLE:
+ return(2);
+ case TH_STATE_WAITING: return((sleep_time > 20) ? 4 : 3);
+ case TH_STATE_STOPPED: return(5);
+ case TH_STATE_HALTED: return(6);
+ default: return(7);
+ }
+}
+ /*01234567 */
+char mach_state_table[] = " RUSITH?";
+
+
+int
+thread_schedinfo(
+ KINFO *ki,
+ thread_port_t thread,
+ policy_t pol,
+ void * buf)
+{
+ unsigned int count;
+ int ret = KERN_FAILURE;
+
+ switch (pol) {
+
+ case POLICY_TIMESHARE:
+ count = POLICY_TIMESHARE_INFO_COUNT;
+ ret = thread_info(thread, THREAD_SCHED_TIMESHARE_INFO,
+ (thread_info_t)buf, &count);
+ if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_timeshare_info *)buf)->cur_priority)))
+ ki->curpri = ((struct policy_timeshare_info *)buf)->cur_priority;
+ break;
+
+ case POLICY_FIFO:
+ count = POLICY_FIFO_INFO_COUNT;
+ ret = thread_info(thread, THREAD_SCHED_FIFO_INFO,
+ buf, &count);
+ if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_fifo_info *)buf)->base_priority)))
+ ki->curpri = ((struct policy_fifo_info *)buf)->base_priority;
+ break;
+
+ case POLICY_RR:
+ count = POLICY_RR_INFO_COUNT;
+ ret = thread_info(thread, THREAD_SCHED_RR_INFO,
+ buf, &count);
+ if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_rr_info *)buf)->base_priority)))
+ ki->curpri = ((struct policy_rr_info *)buf)->base_priority;
+ break;
+ }
+ return(ret);
+}
+
+int get_task_info (KINFO *ki)
+{
+ kern_return_t error;
+ unsigned int info_count = TASK_BASIC_INFO_COUNT;
+ unsigned int thread_info_count = THREAD_BASIC_INFO_COUNT;
+ pid_t pid;
+ int j, err = 0;
+
+ ki->state = STATE_MAX;
+
+ pid = KI_PROC(ki)->p_pid;
+ if (task_for_pid(mach_task_self(), pid, &ki->task) != KERN_SUCCESS) {
+ return(1);
+ }
+ info_count = TASK_BASIC_INFO_COUNT;
+ error = task_info(ki->task, TASK_BASIC_INFO, (task_info_t)&ki->tasks_info, &info_count);
+ if (error != KERN_SUCCESS) {
+ ki->invalid_tinfo=1;
+#ifdef DEBUG
+ mach_error("Error calling task_info()", error);
+#endif
+ return(1);
+ }
+ {
+ vm_region_basic_info_data_64_t b_info;
+ vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT;
+ vm_size_t size;
+ mach_port_t object_name;
+
+ /*
+ * try to determine if this task has the split libraries
+ * mapped in... if so, adjust its virtual size down by
+ * the 2 segments that are used for split libraries
+ */
+ info_count = VM_REGION_BASIC_INFO_COUNT_64;
+ error = vm_region_64(ki->task, &address, &size, VM_REGION_BASIC_INFO,
+ (vm_region_info_t)&b_info, &info_count, &object_name);
+ if (error == KERN_SUCCESS) {
+ if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) &&
+ ki->tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE))
+ ki->tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
+ }
+ }
+ info_count = TASK_THREAD_TIMES_INFO_COUNT;
+ error = task_info(ki->task, TASK_THREAD_TIMES_INFO, (task_info_t)&ki->times, &info_count);
+ if (error != KERN_SUCCESS) {
+ ki->invalid_tinfo=1;
+#ifdef DEBUG
+ mach_error("Error calling task_info()", error);
+#endif
+ return(1);
+ }
+ switch(ki->tasks_info.policy) {
+ case POLICY_TIMESHARE :
+ info_count = POLICY_TIMESHARE_INFO_COUNT;
+ error = task_info(ki->task, TASK_SCHED_TIMESHARE_INFO, (task_info_t)&ki->schedinfo.tshare, &info_count);
+ if (error != KERN_SUCCESS) {
+ ki->invalid_tinfo=1;
+#ifdef DEBUG
+ mach_error("Error calling task_info()", error);
+#endif
+ return(1);
+ }
+
+ ki->curpri = ki->schedinfo.tshare.cur_priority;
+ ki->basepri = ki->schedinfo.tshare.base_priority;
+ break;
+ case POLICY_RR :
+ info_count = POLICY_RR_INFO_COUNT;
+ error = task_info(ki->task, TASK_SCHED_RR_INFO, (task_info_t)&ki->schedinfo.rr, &info_count);
+ if (error != KERN_SUCCESS) {
+ ki->invalid_tinfo=1;
+#ifdef DEBUG
+ mach_error("Error calling task_info()", error);
+#endif
+ return(1);
+ }
+
+ ki->curpri = ki->schedinfo.rr.base_priority;
+ ki->basepri = ki->schedinfo.rr.base_priority;
+ break;
+
+ case POLICY_FIFO :
+ info_count = POLICY_FIFO_INFO_COUNT;
+ error = task_info(ki->task, TASK_SCHED_FIFO_INFO, (task_info_t)&ki->schedinfo.fifo, &info_count);
+ if (error != KERN_SUCCESS) {
+ ki->invalid_tinfo=1;
+#ifdef DEBUG
+ mach_error("Error calling task_info()", error);
+#endif
+ return(1);
+ }
+
+ ki->curpri = ki->schedinfo.fifo.base_priority;
+ ki->basepri = ki->schedinfo.fifo.base_priority;
+ break;
+ }
+
+ ki->invalid_tinfo=0;
+
+ ki->cpu_usage=0;
+ error = task_threads(ki->task, &ki->thread_list, &ki->thread_count);
+ if (error != KERN_SUCCESS) {
+ mach_port_deallocate(mach_task_self(),ki->task);
+#ifdef DEBUG
+ mach_error("Call to task_threads() failed", error);
+#endif
+ return(1);
+ }
+ err=0;
+ //ki->curpri = 255;
+ //ki->basepri = 255;
+ ki->swapped = 1;
+ ki->thval = calloc(ki->thread_count, sizeof(struct thread_values));
+ for (j = 0; j < ki->thread_count; j++) {
+ int tstate;
+ thread_info_count = THREAD_BASIC_INFO_COUNT;
+ error = thread_info(ki->thread_list[j], THREAD_BASIC_INFO,
+ (thread_info_t)&ki->thval[j].tb,
+ &thread_info_count);
+ if (error != KERN_SUCCESS) {
+#ifdef DEBUG
+ mach_error("Call to thread_info() failed", error);
+#endif
+ err=1;
+ } else {
+ ki->cpu_usage += ki->thval[j].tb.cpu_usage;
+ }
+ error = thread_schedinfo(ki, ki->thread_list[j],
+ ki->thval[j].tb.policy, &ki->thval[j].schedinfo);
+ if (error != KERN_SUCCESS) {
+#ifdef DEBUG
+ mach_error("Call to thread_schedinfo() failed", error);
+#endif
+ err=1;
+ }
+ tstate = mach_state_order(ki->thval[j].tb.run_state,
+ ki->thval[j].tb.sleep_time);
+ if (tstate < ki->state)
+ ki->state = tstate;
+ if ((ki->thval[j].tb.flags & TH_FLAGS_SWAPPED ) == 0)
+ ki->swapped = 0;
+ mach_port_deallocate(mach_task_self(),
+ ki->thread_list[j]);
+ }
+ ki->invalid_thinfo = err;
+ /* Deallocate the list of threads. */
+ error = vm_deallocate(mach_task_self(),
+ (vm_address_t)(ki->thread_list),
+ sizeof(*ki->thread_list) * ki->thread_count);
+ if (error != KERN_SUCCESS) {
+#ifdef DEBUG
+ mach_error("Trouble freeing thread_list", error);
+#endif
+ }
+
+ mach_port_deallocate(mach_task_self(),ki->task);
+ return(0);
+}