Changeset dec16a2 in mainline for uspace/app/top/top.c
- Timestamp:
- 2010-04-18T16:52:47Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5c45ca8
- Parents:
- e535eeb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/top/top.c
re535eeb rdec16a2 1 1 /* 2 2 * Copyright (c) 2010 Stanislav Kozina 3 * Copyright (c) 2010 Martin Decky 3 4 * All rights reserved. 4 5 * … … 38 39 #include <stdlib.h> 39 40 #include <unistd.h> 40 #include <uptime.h>41 41 #include <task.h> 42 42 #include <thread.h> 43 43 #include <sys/time.h> 44 #include <load.h>45 #include <ps.h>46 44 #include <arch/barrier.h> 45 #include <errno.h> 47 46 #include "screen.h" 48 47 #include "input.h" 49 48 #include "top.h" 50 #include "ps.h" 51 52 #define UPDATE_INTERVAL 1 53 54 #define DAY 86400 55 #define HOUR 3600 56 #define MINUTE 60 49 50 #define NAME "top" 51 52 #define UPDATE_INTERVAL 1 53 54 #define DAY 86400 55 #define HOUR 3600 56 #define MINUTE 60 57 57 58 58 int operation_type; 59 59 60 static voidread_data(data_t *target)60 static const char *read_data(data_t *target) 61 61 { 62 /* Read current time */ 62 /* Initialize data */ 63 target->load = NULL; 64 target->cpus = NULL; 65 target->cpus_perc = NULL; 66 target->tasks = NULL; 67 target->tasks_perc = NULL; 68 target->threads = NULL; 69 target->physmem = NULL; 70 71 /* Get current time */ 63 72 struct timeval time; 64 if (gettimeofday(&time, NULL) != 0) { 65 printf("Cannot get time of day!\n"); 66 exit(1); 67 } 73 if (gettimeofday(&time, NULL) != EOK) 74 return "Cannot get time of day"; 75 68 76 target->hours = (time.tv_sec % DAY) / HOUR; 69 77 target->minutes = (time.tv_sec % HOUR) / MINUTE; 70 78 target->seconds = time.tv_sec % MINUTE; 71 72 /* Read uptime */ 73 uint64_t uptime; 74 get_uptime(&uptime); 75 target->uptime_d = uptime / DAY; 76 target->uptime_h = (uptime % DAY) / HOUR; 77 target->uptime_m = (uptime % HOUR) / MINUTE; 78 target->uptime_s = uptime % MINUTE; 79 80 /* Read load */ 81 get_load(target->load); 82 83 /* Read task ids */ 84 target->task_count = get_tasks(&target->taskinfos); 85 86 /* Read all threads */ 87 target->thread_count = get_threads(&target->thread_infos); 88 89 /* Read cpu infos */ 90 target->cpu_count = get_cpu_infos(&target->cpus); 91 92 /* Read mem info */ 93 get_mem_info(&target->mem_info); 79 80 /* Get uptime */ 81 sysarg_t uptime = stats_get_uptime(); 82 target->udays = uptime / DAY; 83 target->uhours = (uptime % DAY) / HOUR; 84 target->uminutes = (uptime % HOUR) / MINUTE; 85 target->useconds = uptime % MINUTE; 86 87 /* Get load */ 88 target->load = stats_get_load(&(target->load_count)); 89 if (target->load == NULL) 90 return "Cannot get system load"; 91 92 /* Get CPUs */ 93 target->cpus = stats_get_cpus(&(target->cpus_count)); 94 if (target->cpus == NULL) 95 return "Cannot get CPUs"; 96 97 target->cpus_perc = 98 (perc_cpu_t *) calloc(target->cpus_count, sizeof(perc_cpu_t)); 99 if (target->cpus_perc == NULL) 100 return "Not enough memory for CPU utilization"; 101 102 /* Get tasks */ 103 target->tasks = stats_get_tasks(&(target->tasks_count)); 104 if (target->tasks == NULL) 105 return "Cannot get tasks"; 106 107 target->tasks_perc = 108 (perc_task_t *) calloc(target->tasks_count, sizeof(perc_task_t)); 109 if (target->tasks_perc == NULL) 110 return "Not enough memory for task utilization"; 111 112 /* Get threads */ 113 target->threads = stats_get_threads(&(target->threads_count)); 114 if (target->threads == NULL) 115 return "Cannot get threads"; 116 117 /* Get physical memory */ 118 target->physmem = stats_get_physmem(); 119 if (target->physmem == NULL) 120 return "Cannot get physical memory"; 121 122 return NULL; 94 123 } 95 124 96 125 /** Computes percentage differencies from old_data to new_data 97 126 * 98 * @param old_data 99 * @param new_data 100 * 101 */ 102 static voidcompute_percentages(data_t *old_data, data_t *new_data)127 * @param old_data Pointer to old data strucutre. 128 * @param new_data Pointer to actual data where percetages are stored. 129 * 130 */ 131 static const char *compute_percentages(data_t *old_data, data_t *new_data) 103 132 { 104 /* Foreach cpu, compute total ticks and divide it between user and 105 * system */ 106 unsigned int i; 107 new_data->cpu_perc = malloc(new_data->cpu_count * sizeof(cpu_perc_t)); 108 for (i = 0; i < new_data->cpu_count; ++i) { 109 uint64_t idle = new_data->cpus[i].idle_ticks - old_data->cpus[i].idle_ticks; 110 uint64_t busy = new_data->cpus[i].busy_ticks - old_data->cpus[i].busy_ticks; 133 /* Allocate memory */ 134 135 uint64_t *ucycles_diff = calloc(new_data->tasks_count, sizeof(uint64_t)); 136 if (ucycles_diff == NULL) 137 return "Not enough memory for user utilization"; 138 139 uint64_t *kcycles_diff = calloc(new_data->tasks_count, sizeof(uint64_t)); 140 if (kcycles_diff == NULL) { 141 free(ucycles_diff); 142 return "Not enough memory for kernel utilization"; 143 } 144 145 /* For each CPU: Compute total ticks and divide it between 146 user and kernel */ 147 148 size_t i; 149 for (i = 0; i < new_data->cpus_count; i++) { 150 uint64_t idle = 151 new_data->cpus[i].idle_ticks - old_data->cpus[i].idle_ticks; 152 uint64_t busy = 153 new_data->cpus[i].busy_ticks - old_data->cpus[i].busy_ticks; 111 154 uint64_t sum = idle + busy; 112 FRACTION_TO_FLOAT(new_data->cpu_perc[i].idle, idle * 100, sum); 113 FRACTION_TO_FLOAT(new_data->cpu_perc[i].busy, busy * 100, sum); 114 } 115 155 156 FRACTION_TO_FLOAT(new_data->cpus_perc[i].idle, idle * 100, sum); 157 FRACTION_TO_FLOAT(new_data->cpus_perc[i].busy, busy * 100, sum); 158 } 159 116 160 /* For all tasks compute sum and differencies of all cycles */ 117 uint64_t mem_total = 1; /*< Must NOT be null! */ 118 uint64_t ucycles_total = 1; /*< Must NOT be null! */ 119 uint64_t kcycles_total = 1; /*< Must NOT be null! */ 120 uint64_t *ucycles_diff = malloc(new_data->task_count * sizeof(uint64_t)); 121 uint64_t *kcycles_diff = malloc(new_data->task_count * sizeof(uint64_t)); 122 unsigned int j = 0; 123 for (i = 0; i < new_data->task_count; ++i) { 124 /* Jump over all death tasks */ 125 while (old_data->taskinfos[j].taskid < new_data->taskinfos[i].taskid) 126 ++j; 127 if (old_data->taskinfos[j].taskid > new_data->taskinfos[i].taskid) { 161 162 uint64_t virtmem_total = 1; /* Must NOT be zero */ 163 uint64_t ucycles_total = 1; /* Must NOT be zero */ 164 uint64_t kcycles_total = 1; /* Must NOT be zero */ 165 166 for (i = 0; i < new_data->tasks_count; i++) { 167 /* Match task with the previous instance */ 168 169 bool found = false; 170 size_t j; 171 for (j = 0; j < old_data->tasks_count; j++) { 172 if (new_data->tasks[i].task_id == old_data->tasks[j].task_id) { 173 found = true; 174 break; 175 } 176 } 177 178 if (!found) { 128 179 /* This is newly borned task, ignore it */ 129 180 ucycles_diff[i] = 0; … … 131 182 continue; 132 183 } 133 /* Now we now we have task with same id */ 134 ucycles_diff[i] = new_data->taskinfos[i].ucycles - old_data->taskinfos[j].ucycles; 135 kcycles_diff[i] = new_data->taskinfos[i].kcycles - old_data->taskinfos[j].kcycles; 136 137 mem_total += new_data->taskinfos[i].virt_mem; 184 185 ucycles_diff[i] = 186 new_data->tasks[i].ucycles - old_data->tasks[j].ucycles; 187 kcycles_diff[i] = 188 new_data->tasks[i].kcycles - old_data->tasks[j].kcycles; 189 190 virtmem_total += new_data->tasks[i].virtmem; 138 191 ucycles_total += ucycles_diff[i]; 139 192 kcycles_total += kcycles_diff[i]; 140 193 } 141 142 /* And now compute percental change */ 143 new_data->task_perc = malloc(new_data->task_count * sizeof(task_perc_t)); 144 for (i = 0; i < new_data->task_count; ++i) { 145 FRACTION_TO_FLOAT(new_data->task_perc[i].mem, new_data->taskinfos[i].virt_mem * 100, mem_total); 146 FRACTION_TO_FLOAT(new_data->task_perc[i].ucycles, ucycles_diff[i] * 100, ucycles_total); 147 FRACTION_TO_FLOAT(new_data->task_perc[i].kcycles, kcycles_diff[i] * 100, kcycles_total); 148 } 149 150 /* Wait until coprocessor finishes its work */ 151 write_barrier(); 152 153 /* And free temporary structures */ 194 195 /* For each task: Compute percential change */ 196 197 for (i = 0; i < new_data->tasks_count; i++) { 198 FRACTION_TO_FLOAT(new_data->tasks_perc[i].virtmem, 199 new_data->tasks[i].virtmem * 100, virtmem_total); 200 FRACTION_TO_FLOAT(new_data->tasks_perc[i].ucycles, 201 ucycles_diff[i] * 100, ucycles_total); 202 FRACTION_TO_FLOAT(new_data->tasks_perc[i].kcycles, 203 kcycles_diff[i] * 100, kcycles_total); 204 } 205 206 /* Cleanup */ 207 154 208 free(ucycles_diff); 155 209 free(kcycles_diff); 210 211 return NULL; 156 212 } 157 213 158 214 static void free_data(data_t *target) 159 215 { 160 free(target->taskinfos); 161 free(target->thread_infos); 162 free(target->cpus); 163 free(target->cpu_perc); 164 free(target->task_perc); 216 if (target->load != NULL) 217 free(target->load); 218 219 if (target->cpus != NULL) 220 free(target->cpus); 221 222 if (target->cpus_perc != NULL) 223 free(target->cpus_perc); 224 225 if (target->tasks != NULL) 226 free(target->tasks); 227 228 if (target->tasks_perc != NULL) 229 free(target->tasks_perc); 230 231 if (target->threads != NULL) 232 free(target->threads); 233 234 if (target->physmem != NULL) 235 free(target->physmem); 165 236 } 166 167 static inline void swap(data_t **first, data_t **second)168 {169 data_t *temp;170 temp = *first;171 *first = *second;172 *second = temp;173 }174 175 static data_t data[2];176 237 177 238 int main(int argc, char *argv[]) 178 239 { 179 data_t *data1 = &data[0]; 180 data_t *data2 = &data[1]; 240 data_t data; 241 data_t data_prev; 242 const char *ret = NULL; 243 181 244 screen_init(); 182 183 /* Read initial stats */184 245 printf("Reading initial data...\n"); 185 read_data(data1); 246 247 if ((ret = read_data(&data_prev)) != NULL) 248 goto out; 249 186 250 /* Compute some rubbish to have initialised values */ 187 compute_percentages(data1, data1); 188 189 /* And paint screen until death... */ 251 if ((ret = compute_percentages(&data_prev, &data_prev)) != NULL) 252 goto out; 253 254 /* And paint screen until death */ 190 255 operation_type = OP_TASKS; 191 256 while (true) { 192 257 char c = tgetchar(UPDATE_INTERVAL); 193 258 if (c < 0) { 194 read_data(data2); 195 compute_percentages(data1, data2); 196 free_data(data1); 197 print_data(data2); 198 swap(&data1, &data2); 259 if ((ret = read_data(&data)) != NULL) { 260 free_data(&data); 261 goto out; 262 } 263 264 if ((ret = compute_percentages(&data_prev, &data)) != NULL) { 265 free_data(&data); 266 goto out; 267 } 268 269 print_data(&data); 270 free_data(&data_prev); 271 data_prev = data; 272 199 273 continue; 200 274 } 275 201 276 switch (c) { 202 277 case 'q': 203 clear_screen(); 204 return 0; 278 goto out; 205 279 case 'i': 206 PRINT_WARNING("Showing IPC statistics", c);280 print_warning("Showing IPC statistics"); 207 281 operation_type = OP_IPC; 208 282 break; 209 283 case 't': 210 PRINT_WARNING("Showing task stats", c);284 print_warning("Showing task statistics"); 211 285 operation_type = OP_TASKS; 212 286 break; 213 287 default: 214 PRINT_WARNING("Unknown command: %c", c);288 print_warning("Unknown command: %c", c); 215 289 break; 216 290 } 217 218 } 219 220 free_data(data1); 221 free_data(data2); 291 } 292 293 out: 294 screen_done(); 295 free_data(&data_prev); 296 297 if (ret != NULL) { 298 fprintf(stderr, "%s: %s\n", NAME, ret); 299 return 1; 300 } 301 222 302 return 0; 223 303 }
Note:
See TracChangeset
for help on using the changeset viewer.