1 /* 2 * Copyright 2002-2008, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Francois Revol (mmu_man) 7 * Salvatore Benedetto <salvatore.benedetto@gmail.com> 8 * Bjoern Herzig (xRaich[o]2x) 9 * Thomas Schmidt <thomas.compix@googlemail.com> 10 */ 11 #include <stdio.h> 12 #include <unistd.h> 13 #include <string.h> 14 15 #include <OS.h> 16 17 18 enum { 19 Team = 0, 20 Id, 21 Threads, 22 Gid, 23 Uid 24 }; 25 26 struct ColumnIndo { 27 const char* name; 28 const char* header; 29 const char* format; 30 } Infos[] = { 31 { "Team", "%-50s", "%-50s" }, 32 { "Id", "%5s", "%5" B_PRId32 }, 33 { "Threads", "#%7s", "%8" B_PRId32 }, 34 { "Gid", "%4s", "%4d" }, 35 { "Uid", "%4s", "%4d" } 36 }; 37 38 #define maxColumns 10 39 int Columns[maxColumns] = { Team, Id, Threads, Gid, Uid, 0 }; 40 int ColumnsCount = 5; 41 42 const char* sStates[] = {"run", "rdy", "msg", "zzz", "sus", "wait"}; 43 44 static void printTeamThreads(team_info* teamInfo, bool printSemaphoreInfo); 45 static void printTeamInfo(team_info* teamInfo, bool printHeader); 46 47 48 static void 49 printTeamInfo(team_info* teamInfo, bool printHeader) 50 { 51 int i = 0; 52 if (printHeader) { 53 for (i = 0; i < ColumnsCount; i++) { 54 printf(Infos[Columns[i]].header, Infos[Columns[i]].name); 55 putchar(' '); 56 } 57 puts(""); 58 } 59 60 61 for (i = 0; i < ColumnsCount; i++) { 62 switch (Columns[i]) { 63 case Team: 64 printf(Infos[Team].format, teamInfo->args); 65 break; 66 case Id: 67 printf(Infos[Id].format, teamInfo->team); 68 break; 69 case Threads: 70 printf(Infos[Threads].format, teamInfo->thread_count); 71 break; 72 case Gid: 73 printf(Infos[Gid].format, teamInfo->gid); 74 break; 75 case Uid: 76 printf(Infos[Uid].format, teamInfo->uid); 77 break; 78 } 79 putchar(' '); 80 } 81 puts(""); 82 } 83 84 85 static void 86 printTeamThreads(team_info* teamInfo, bool printSemaphoreInfo) 87 { 88 const char* threadState; 89 int32 threadCookie = 0; 90 sem_info semaphoreInfo; 91 thread_info threadInfo; 92 93 // Print all info about its threads too 94 while (get_next_thread_info(teamInfo->team, &threadCookie, &threadInfo) 95 >= B_OK) { 96 if (threadInfo.state < B_THREAD_RUNNING 97 || threadInfo.state > B_THREAD_WAITING) 98 // This should never happen 99 threadState = "???"; 100 else 101 threadState = sStates[threadInfo.state - 1]; 102 103 printf("%-37s %5" B_PRId32 " %8s %4" B_PRId32 " %8" B_PRIu64 " %8" 104 B_PRId64 " ", threadInfo.name, threadInfo.thread, threadState, 105 threadInfo.priority, (threadInfo.user_time / 1000), 106 (threadInfo.kernel_time / 1000)); 107 108 if (printSemaphoreInfo) { 109 if (threadInfo.state == B_THREAD_WAITING && threadInfo.sem != -1) { 110 status_t status = get_sem_info(threadInfo.sem, &semaphoreInfo); 111 if (status == B_OK) { 112 printf("%s(%" B_PRId32 ")\n", semaphoreInfo.name, 113 semaphoreInfo.sem); 114 } else { 115 printf("%s(%" B_PRId32 ")\n", strerror(status), 116 threadInfo.sem); 117 } 118 } else 119 puts(""); 120 } else 121 puts(""); 122 } 123 } 124 125 126 int 127 main(int argc, char** argv) 128 { 129 team_info teamInfo; 130 int32 teamCookie = 0; 131 system_info systemInfo; 132 bool printSystemInfo = false; 133 bool printThreads = false; 134 bool printHeader = true; 135 bool printSemaphoreInfo = false; 136 bool customizeColumns = false; 137 // match this in team name 138 char* string_to_match; 139 140 int c; 141 142 while ((c = getopt(argc, argv, "-ihaso:")) != EOF) { 143 switch (c) { 144 case 'i': 145 printSystemInfo = true; 146 break; 147 case 'h': 148 printf( "usage: ps [-hais] [-o columns list] [team]\n" 149 "-h : show help\n" 150 "-i : show system info\n" 151 "-s : show semaphore info\n" 152 "-o : display team info associated with the list\n" 153 "-a : show threads too (by default only teams are " 154 "displayed)\n"); 155 return 0; 156 break; 157 case 'a': 158 printThreads = true; 159 break; 160 case 's': 161 printSemaphoreInfo = true; 162 break; 163 case 'o': 164 if (!customizeColumns) 165 ColumnsCount = 0; 166 customizeColumns = true; 167 /* fallthrough */ 168 case 1: 169 { 170 size_t i = 0; 171 if (c == 1 && !customizeColumns) 172 break; 173 for (i = 0; i < sizeof(Infos) / sizeof(Infos[0]); i++) 174 if (strcmp(optarg, Infos[i].name) == 0 175 && ColumnsCount < maxColumns) { 176 Columns[ColumnsCount++] = i; 177 continue; 178 } 179 break; 180 } 181 } 182 } 183 184 // TODO: parse command line 185 // Possible command line options: 186 // -t pstree like output 187 188 if (argc == 2 && (printSystemInfo || printThreads)) 189 string_to_match = NULL; 190 else 191 string_to_match = (argc >= 2 && !customizeColumns) 192 ? argv[argc - 1] : NULL; 193 194 if (!string_to_match) { 195 while (get_next_team_info(&teamCookie, &teamInfo) >= B_OK) { 196 printTeamInfo(&teamInfo, printHeader); 197 printHeader = false; 198 if (printThreads) { 199 printf("\n%-37s %5s %8s %4s %8s %8s\n", "Thread", "Id", \ 200 "State", "Prio", "UTime", "KTime"); 201 printTeamThreads(&teamInfo, printSemaphoreInfo); 202 printf("----------------------------------------------" \ 203 "-----------------------------\n"); 204 printHeader = true; 205 } 206 } 207 } else { 208 while (get_next_team_info(&teamCookie, &teamInfo) >= B_OK) { 209 char* p = teamInfo.args; 210 if ((p = strchr(p, ' '))) 211 *p = '\0'; /* remove arguments, keep only argv[0] */ 212 p = strrchr(teamInfo.args, '/'); /* forget the path */ 213 if (p == NULL) 214 p = teamInfo.args; 215 if (strstr(p, string_to_match) == NULL) 216 continue; 217 printTeamInfo(&teamInfo, true); 218 printf("\n%-37s %5s %8s %4s %8s %8s\n", "Thread", "Id", "State", \ 219 "Prio", "UTime", "KTime"); 220 printTeamThreads(&teamInfo, printSemaphoreInfo); 221 } 222 } 223 224 if (printSystemInfo) { 225 // system stats 226 get_system_info(&systemInfo); 227 printf("\nSystem Info\n"); 228 printf("%" B_PRIu64 "k (%" B_PRIu64 " bytes) total memory\n", 229 (systemInfo.max_pages * B_PAGE_SIZE / 1024), 230 (systemInfo.max_pages * B_PAGE_SIZE)); 231 printf("%" B_PRIu64 "k (%" B_PRIu64 " bytes) currently committed\n", 232 (systemInfo.used_pages * B_PAGE_SIZE / 1024), 233 (systemInfo.used_pages * B_PAGE_SIZE)); 234 printf("%" B_PRIu64 "k (%" B_PRIu64 " bytes) currently available\n", 235 (systemInfo.max_pages - systemInfo.used_pages) * B_PAGE_SIZE / 1024, 236 (systemInfo.max_pages - systemInfo.used_pages) * B_PAGE_SIZE); 237 printf("%2.1f%% memory utilisation\n", 238 (float)100 * systemInfo.used_pages / systemInfo.max_pages); 239 } 240 return 0; 241 } 242