1#include <sys/param.h> 2#include <sys/user.h> 3#include <sys/time.h> 4#include <sys/resource.h> 5#include <sys/stat.h> 6#include <sys/ioctl.h> 7#include <sys/sysctl.h> 8 9#include <ctype.h> 10#include <err.h> 11#include <errno.h> 12#include <fcntl.h> 13#include <limits.h> 14#include <nlist.h> 15#include <paths.h> 16#include <stdio.h> 17#include <stdlib.h> 18#include <string.h> 19#include <unistd.h> 20#include <locale.h> 21#include <pwd.h> 22 23#include "ps.h" 24#include <mach/shared_memory_server.h> 25 26extern kern_return_t task_for_pid(task_port_t task, pid_t pid, task_port_t *target); 27 28#define STATE_MAX 7 29 30int 31mach_state_order(s, sleep_time) 32int s; 33long sleep_time; 34{ 35switch (s) { 36case TH_STATE_RUNNING: return(1); 37case TH_STATE_UNINTERRUPTIBLE: 38 return(2); 39 case TH_STATE_WAITING: return((sleep_time > 20) ? 4 : 3); 40 case TH_STATE_STOPPED: return(5); 41 case TH_STATE_HALTED: return(6); 42 default: return(7); 43 } 44} 45 /*01234567 */ 46char mach_state_table[] = " RUSITH?"; 47 48 49int 50thread_schedinfo( 51 KINFO *ki, 52 thread_port_t thread, 53 policy_t pol, 54 void * buf) 55{ 56 unsigned int count; 57 int ret = KERN_FAILURE; 58 59 switch (pol) { 60 61 case POLICY_TIMESHARE: 62 count = POLICY_TIMESHARE_INFO_COUNT; 63 ret = thread_info(thread, THREAD_SCHED_TIMESHARE_INFO, 64 (thread_info_t)buf, &count); 65 if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_timeshare_info *)buf)->cur_priority))) 66 ki->curpri = ((struct policy_timeshare_info *)buf)->cur_priority; 67 break; 68 69 case POLICY_FIFO: 70 count = POLICY_FIFO_INFO_COUNT; 71 ret = thread_info(thread, THREAD_SCHED_FIFO_INFO, 72 buf, &count); 73 if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_fifo_info *)buf)->base_priority))) 74 ki->curpri = ((struct policy_fifo_info *)buf)->base_priority; 75 break; 76 77 case POLICY_RR: 78 count = POLICY_RR_INFO_COUNT; 79 ret = thread_info(thread, THREAD_SCHED_RR_INFO, 80 buf, &count); 81 if((ret == KERN_SUCCESS) && (ki->curpri < (((struct policy_rr_info *)buf)->base_priority))) 82 ki->curpri = ((struct policy_rr_info *)buf)->base_priority; 83 break; 84 } 85 return(ret); 86} 87 88int get_task_info (KINFO *ki) 89{ 90 kern_return_t error; 91 unsigned int info_count = TASK_BASIC_INFO_COUNT; 92 unsigned int thread_info_count = THREAD_BASIC_INFO_COUNT; 93 pid_t pid; 94 int j, err = 0; 95 96 ki->state = STATE_MAX; 97 98 pid = KI_PROC(ki)->p_pid; 99 if (task_for_pid(mach_task_self(), pid, &ki->task) != KERN_SUCCESS) { 100 return(1); 101 } 102 info_count = TASK_BASIC_INFO_COUNT; 103 error = task_info(ki->task, TASK_BASIC_INFO, (task_info_t)&ki->tasks_info, &info_count); 104 if (error != KERN_SUCCESS) { 105 ki->invalid_tinfo=1; 106#ifdef DEBUG 107 mach_error("Error calling task_info()", error); 108#endif 109 return(1); 110 } 111 { 112 vm_region_basic_info_data_64_t b_info; 113 vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT; 114 vm_size_t size; 115 mach_port_t object_name; 116 117 /* 118 * try to determine if this task has the split libraries 119 * mapped in... if so, adjust its virtual size down by 120 * the 2 segments that are used for split libraries 121 */ 122 info_count = VM_REGION_BASIC_INFO_COUNT_64; 123 error = vm_region_64(ki->task, &address, &size, VM_REGION_BASIC_INFO, 124 (vm_region_info_t)&b_info, &info_count, &object_name); 125 if (error == KERN_SUCCESS) { 126 if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) && 127 ki->tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE)) 128 ki->tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE); 129 } 130 } 131 info_count = TASK_THREAD_TIMES_INFO_COUNT; 132 error = task_info(ki->task, TASK_THREAD_TIMES_INFO, (task_info_t)&ki->times, &info_count); 133 if (error != KERN_SUCCESS) { 134 ki->invalid_tinfo=1; 135#ifdef DEBUG 136 mach_error("Error calling task_info()", error); 137#endif 138 return(1); 139 } 140 switch(ki->tasks_info.policy) { 141 case POLICY_TIMESHARE : 142 info_count = POLICY_TIMESHARE_INFO_COUNT; 143 error = task_info(ki->task, TASK_SCHED_TIMESHARE_INFO, (task_info_t)&ki->schedinfo.tshare, &info_count); 144 if (error != KERN_SUCCESS) { 145 ki->invalid_tinfo=1; 146#ifdef DEBUG 147 mach_error("Error calling task_info()", error); 148#endif 149 return(1); 150 } 151 152 ki->curpri = ki->schedinfo.tshare.cur_priority; 153 ki->basepri = ki->schedinfo.tshare.base_priority; 154 break; 155 case POLICY_RR : 156 info_count = POLICY_RR_INFO_COUNT; 157 error = task_info(ki->task, TASK_SCHED_RR_INFO, (task_info_t)&ki->schedinfo.rr, &info_count); 158 if (error != KERN_SUCCESS) { 159 ki->invalid_tinfo=1; 160#ifdef DEBUG 161 mach_error("Error calling task_info()", error); 162#endif 163 return(1); 164 } 165 166 ki->curpri = ki->schedinfo.rr.base_priority; 167 ki->basepri = ki->schedinfo.rr.base_priority; 168 break; 169 170 case POLICY_FIFO : 171 info_count = POLICY_FIFO_INFO_COUNT; 172 error = task_info(ki->task, TASK_SCHED_FIFO_INFO, (task_info_t)&ki->schedinfo.fifo, &info_count); 173 if (error != KERN_SUCCESS) { 174 ki->invalid_tinfo=1; 175#ifdef DEBUG 176 mach_error("Error calling task_info()", error); 177#endif 178 return(1); 179 } 180 181 ki->curpri = ki->schedinfo.fifo.base_priority; 182 ki->basepri = ki->schedinfo.fifo.base_priority; 183 break; 184 } 185 186 ki->invalid_tinfo=0; 187 188 ki->cpu_usage=0; 189 error = task_threads(ki->task, &ki->thread_list, &ki->thread_count); 190 if (error != KERN_SUCCESS) { 191 mach_port_deallocate(mach_task_self(),ki->task); 192#ifdef DEBUG 193 mach_error("Call to task_threads() failed", error); 194#endif 195 return(1); 196 } 197 err=0; 198 //ki->curpri = 255; 199 //ki->basepri = 255; 200 ki->swapped = 1; 201 ki->thval = malloc(ki->thread_count * sizeof(struct thread_values)); 202 for (j = 0; j < ki->thread_count; j++) { 203 int tstate; 204 thread_info_count = THREAD_BASIC_INFO_COUNT; 205 error = thread_info(ki->thread_list[j], THREAD_BASIC_INFO, 206 (thread_info_t)&ki->thval[j].tb, 207 &thread_info_count); 208 if (error != KERN_SUCCESS) { 209#ifdef DEBUG 210 mach_error("Call to thread_info() failed", error); 211#endif 212 err=1; 213 } 214 error = thread_schedinfo(ki, ki->thread_list[j], 215 ki->thval[j].tb.policy, &ki->thval[j].schedinfo); 216 if (error != KERN_SUCCESS) { 217#ifdef DEBUG 218 mach_error("Call to thread_info() failed", error); 219#endif 220 err=1; 221 } 222 ki->cpu_usage += ki->thval[j].tb.cpu_usage; 223 tstate = mach_state_order(ki->thval[j].tb.run_state, 224 ki->thval[j].tb.sleep_time); 225 if (tstate < ki->state) 226 ki->state = tstate; 227 if ((ki->thval[j].tb.flags & TH_FLAGS_SWAPPED ) == 0) 228 ki->swapped = 0; 229 mach_port_deallocate(mach_task_self(), 230 ki->thread_list[j]); 231 } 232 ki->invalid_thinfo = err; 233 /* Deallocate the list of threads. */ 234 error = vm_deallocate(mach_task_self(), 235 (vm_address_t)(ki->thread_list), 236 sizeof(*ki->thread_list) * ki->thread_count); 237 if (error != KERN_SUCCESS) { 238#ifdef DEBUG 239 mach_error("Trouble freeing thread_list", error); 240#endif 241 } 242 243 mach_port_deallocate(mach_task_self(),ki->task); 244 return(0); 245} 246