00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <unistd.h>
00041 #include <task.h>
00042 #include <thread.h>
00043 #include <sys/time.h>
00044 #include <arch/barrier.h>
00045 #include <errno.h>
00046 #include <sort.h>
00047 #include "screen.h"
00048 #include "input.h"
00049 #include "top.h"
00050
00051 #define NAME "top"
00052
00053 #define UPDATE_INTERVAL 1
00054
00055 #define DAY 86400
00056 #define HOUR 3600
00057 #define MINUTE 60
00058
00059 op_mode_t op_mode = OP_TASKS;
00060 sort_mode_t sort_mode = SORT_TASK_CYCLES;
00061 bool excs_all = false;
00062
00063 static const char *read_data(data_t *target)
00064 {
00065
00066 target->load = NULL;
00067 target->cpus = NULL;
00068 target->cpus_perc = NULL;
00069 target->tasks = NULL;
00070 target->tasks_perc = NULL;
00071 target->tasks_map = NULL;
00072 target->threads = NULL;
00073 target->exceptions = NULL;
00074 target->exceptions_perc = NULL;
00075 target->physmem = NULL;
00076 target->ucycles_diff = NULL;
00077 target->kcycles_diff = NULL;
00078 target->ecycles_diff = NULL;
00079 target->ecount_diff = NULL;
00080
00081
00082 struct timeval time;
00083 if (gettimeofday(&time, NULL) != EOK)
00084 return "Cannot get time of day";
00085
00086 target->hours = (time.tv_sec % DAY) / HOUR;
00087 target->minutes = (time.tv_sec % HOUR) / MINUTE;
00088 target->seconds = time.tv_sec % MINUTE;
00089
00090
00091 sysarg_t uptime = stats_get_uptime();
00092 target->udays = uptime / DAY;
00093 target->uhours = (uptime % DAY) / HOUR;
00094 target->uminutes = (uptime % HOUR) / MINUTE;
00095 target->useconds = uptime % MINUTE;
00096
00097
00098 target->load = stats_get_load(&(target->load_count));
00099 if (target->load == NULL)
00100 return "Cannot get system load";
00101
00102
00103 target->cpus = stats_get_cpus(&(target->cpus_count));
00104 if (target->cpus == NULL)
00105 return "Cannot get CPUs";
00106
00107 target->cpus_perc =
00108 (perc_cpu_t *) calloc(target->cpus_count, sizeof(perc_cpu_t));
00109 if (target->cpus_perc == NULL)
00110 return "Not enough memory for CPU utilization";
00111
00112
00113 target->tasks = stats_get_tasks(&(target->tasks_count));
00114 if (target->tasks == NULL)
00115 return "Cannot get tasks";
00116
00117 target->tasks_perc =
00118 (perc_task_t *) calloc(target->tasks_count, sizeof(perc_task_t));
00119 if (target->tasks_perc == NULL)
00120 return "Not enough memory for task utilization";
00121
00122 target->tasks_map =
00123 (size_t *) calloc(target->tasks_count, sizeof(size_t));
00124 if (target->tasks_map == NULL)
00125 return "Not enough memory for task map";
00126
00127
00128 target->threads = stats_get_threads(&(target->threads_count));
00129 if (target->threads == NULL)
00130 return "Cannot get threads";
00131
00132
00133 target->exceptions = stats_get_exceptions(&(target->exceptions_count));
00134 if (target->exceptions == NULL)
00135 return "Cannot get exceptions";
00136
00137 target->exceptions_perc =
00138 (perc_exc_t *) calloc(target->exceptions_count, sizeof(perc_exc_t));
00139 if (target->exceptions_perc == NULL)
00140 return "Not enough memory for exception utilization";
00141
00142
00143 target->physmem = stats_get_physmem();
00144 if (target->physmem == NULL)
00145 return "Cannot get physical memory";
00146
00147 target->ucycles_diff = calloc(target->tasks_count,
00148 sizeof(uint64_t));
00149 if (target->ucycles_diff == NULL)
00150 return "Not enough memory for user utilization";
00151
00152
00153 target->kcycles_diff = calloc(target->tasks_count,
00154 sizeof(uint64_t));
00155 if (target->kcycles_diff == NULL)
00156 return "Not enough memory for kernel utilization";
00157
00158 target->ecycles_diff = calloc(target->exceptions_count,
00159 sizeof(uint64_t));
00160 if (target->ecycles_diff == NULL)
00161 return "Not enough memory for exception cycles utilization";
00162
00163 target->ecount_diff = calloc(target->exceptions_count,
00164 sizeof(uint64_t));
00165 if (target->ecount_diff == NULL)
00166 return "Not enough memory for exception count utilization";
00167
00168 return NULL;
00169 }
00170
00177 static void compute_percentages(data_t *old_data, data_t *new_data)
00178 {
00179
00180
00181
00182 size_t i;
00183 for (i = 0; i < new_data->cpus_count; i++) {
00184 uint64_t idle =
00185 new_data->cpus[i].idle_cycles - old_data->cpus[i].idle_cycles;
00186 uint64_t busy =
00187 new_data->cpus[i].busy_cycles - old_data->cpus[i].busy_cycles;
00188 uint64_t sum = idle + busy;
00189
00190 FRACTION_TO_FLOAT(new_data->cpus_perc[i].idle, idle * 100, sum);
00191 FRACTION_TO_FLOAT(new_data->cpus_perc[i].busy, busy * 100, sum);
00192 }
00193
00194
00195
00196 uint64_t virtmem_total = 0;
00197 uint64_t resmem_total = 0;
00198 uint64_t ucycles_total = 0;
00199 uint64_t kcycles_total = 0;
00200
00201 for (i = 0; i < new_data->tasks_count; i++) {
00202
00203
00204 bool found = false;
00205 size_t j;
00206 for (j = 0; j < old_data->tasks_count; j++) {
00207 if (new_data->tasks[i].task_id == old_data->tasks[j].task_id) {
00208 found = true;
00209 break;
00210 }
00211 }
00212
00213 if (!found) {
00214
00215 new_data->ucycles_diff[i] = 0;
00216 new_data->kcycles_diff[i] = 0;
00217 continue;
00218 }
00219
00220 new_data->ucycles_diff[i] =
00221 new_data->tasks[i].ucycles - old_data->tasks[j].ucycles;
00222 new_data->kcycles_diff[i] =
00223 new_data->tasks[i].kcycles - old_data->tasks[j].kcycles;
00224
00225 virtmem_total += new_data->tasks[i].virtmem;
00226 resmem_total += new_data->tasks[i].resmem;
00227 ucycles_total += new_data->ucycles_diff[i];
00228 kcycles_total += new_data->kcycles_diff[i];
00229 }
00230
00231
00232
00233 for (i = 0; i < new_data->tasks_count; i++) {
00234 FRACTION_TO_FLOAT(new_data->tasks_perc[i].virtmem,
00235 new_data->tasks[i].virtmem * 100, virtmem_total);
00236 FRACTION_TO_FLOAT(new_data->tasks_perc[i].resmem,
00237 new_data->tasks[i].resmem * 100, resmem_total);
00238 FRACTION_TO_FLOAT(new_data->tasks_perc[i].ucycles,
00239 new_data->ucycles_diff[i] * 100, ucycles_total);
00240 FRACTION_TO_FLOAT(new_data->tasks_perc[i].kcycles,
00241 new_data->kcycles_diff[i] * 100, kcycles_total);
00242 }
00243
00244
00245
00246 uint64_t ecycles_total = 0;
00247 uint64_t ecount_total = 0;
00248
00249 for (i = 0; i < new_data->exceptions_count; i++) {
00250
00251
00252
00253
00254
00255
00256 bool found = false;
00257 size_t j;
00258 for (j = 0; j < old_data->exceptions_count; j++) {
00259 if (new_data->exceptions[i].id == old_data->exceptions[j].id) {
00260 found = true;
00261 break;
00262 }
00263 }
00264
00265 if (!found) {
00266
00267 new_data->ecycles_diff[i] = 0;
00268 new_data->ecount_diff[i] = 0;
00269 continue;
00270 }
00271
00272 new_data->ecycles_diff[i] =
00273 new_data->exceptions[i].cycles - old_data->exceptions[j].cycles;
00274 new_data->ecount_diff[i] =
00275 new_data->exceptions[i].count - old_data->exceptions[i].count;
00276
00277 ecycles_total += new_data->ecycles_diff[i];
00278 ecount_total += new_data->ecount_diff[i];
00279 }
00280
00281
00282
00283 for (i = 0; i < new_data->exceptions_count; i++) {
00284 FRACTION_TO_FLOAT(new_data->exceptions_perc[i].cycles,
00285 new_data->ecycles_diff[i] * 100, ecycles_total);
00286 FRACTION_TO_FLOAT(new_data->exceptions_perc[i].count,
00287 new_data->ecount_diff[i] * 100, ecount_total);
00288 }
00289 }
00290
00291 static int cmp_data(void *a, void *b, void *arg)
00292 {
00293 size_t ia = *((size_t *) a);
00294 size_t ib = *((size_t *) b);
00295 data_t *data = (data_t *) arg;
00296
00297 uint64_t acycles = data->ucycles_diff[ia] + data->kcycles_diff[ia];
00298 uint64_t bcycles = data->ucycles_diff[ib] + data->kcycles_diff[ib];
00299
00300 if (acycles > bcycles)
00301 return -1;
00302
00303 if (acycles < bcycles)
00304 return 1;
00305
00306 return 0;
00307 }
00308
00309 static void sort_data(data_t *data)
00310 {
00311 size_t i;
00312
00313 for (i = 0; i < data->tasks_count; i++)
00314 data->tasks_map[i] = i;
00315
00316 qsort((void *) data->tasks_map, data->tasks_count,
00317 sizeof(size_t), cmp_data, (void *) data);
00318 }
00319
00320 static void free_data(data_t *target)
00321 {
00322 if (target->load != NULL)
00323 free(target->load);
00324
00325 if (target->cpus != NULL)
00326 free(target->cpus);
00327
00328 if (target->cpus_perc != NULL)
00329 free(target->cpus_perc);
00330
00331 if (target->tasks != NULL)
00332 free(target->tasks);
00333
00334 if (target->tasks_perc != NULL)
00335 free(target->tasks_perc);
00336
00337 if (target->threads != NULL)
00338 free(target->threads);
00339
00340 if (target->exceptions != NULL)
00341 free(target->exceptions);
00342
00343 if (target->exceptions_perc != NULL)
00344 free(target->exceptions_perc);
00345
00346 if (target->physmem != NULL)
00347 free(target->physmem);
00348
00349 if (target->ucycles_diff != NULL)
00350 free(target->ucycles_diff);
00351
00352 if (target->kcycles_diff != NULL)
00353 free(target->kcycles_diff);
00354
00355 if (target->ecycles_diff != NULL)
00356 free(target->ecycles_diff);
00357
00358 if (target->ecount_diff != NULL)
00359 free(target->ecount_diff);
00360 }
00361
00362 int main(int argc, char *argv[])
00363 {
00364 data_t data;
00365 data_t data_prev;
00366 const char *ret = NULL;
00367
00368 screen_init();
00369 printf("Reading initial data...\n");
00370
00371 if ((ret = read_data(&data_prev)) != NULL)
00372 goto out;
00373
00374
00375 compute_percentages(&data_prev, &data_prev);
00376
00377
00378 while (true) {
00379 int c = tgetchar(UPDATE_INTERVAL);
00380 if (c < 0) {
00381 if ((ret = read_data(&data)) != NULL) {
00382 free_data(&data);
00383 goto out;
00384 }
00385
00386 compute_percentages(&data_prev, &data);
00387 sort_data(&data);
00388 print_data(&data);
00389 free_data(&data_prev);
00390 data_prev = data;
00391
00392 continue;
00393 }
00394
00395 switch (c) {
00396 case 't':
00397 print_warning("Showing task statistics");
00398 op_mode = OP_TASKS;
00399 break;
00400 case 'i':
00401 print_warning("Showing IPC statistics");
00402 op_mode = OP_IPC;
00403 break;
00404 case 'e':
00405 print_warning("Showing exception statistics");
00406 op_mode = OP_EXCS;
00407 break;
00408 case 'h':
00409 print_warning("Showing help");
00410 op_mode = OP_HELP;
00411 break;
00412 case 'q':
00413 goto out;
00414 case 'a':
00415 if (op_mode == OP_EXCS) {
00416 excs_all = !excs_all;
00417 if (excs_all)
00418 print_warning("Showing all exceptions");
00419 else
00420 print_warning("Showing only hot exceptions");
00421 break;
00422 }
00423 default:
00424 print_warning("Unknown command \"%c\", use \"h\" for help", c);
00425 break;
00426 }
00427 }
00428
00429 out:
00430 screen_done();
00431 free_data(&data_prev);
00432
00433 if (ret != NULL) {
00434 fprintf(stderr, "%s: %s\n", NAME, ret);
00435 return 1;
00436 }
00437
00438 return 0;
00439 }
00440