screen.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010 Stanislav Kozina
00003  * Copyright (c) 2010 Martin Decky
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * - Redistributions of source code must retain the above copyright
00011  *   notice, this list of conditions and the following disclaimer.
00012  * - Redistributions in binary form must reproduce the above copyright
00013  *   notice, this list of conditions and the following disclaimer in the
00014  *   documentation and/or other materials provided with the distribution.
00015  * - The name of the author may not be used to endorse or promote products
00016  *   derived from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00019  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00020  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00021  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00023  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00024  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00025  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00027  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00038 #include <stdio.h>
00039 #include <io/console.h>
00040 #include <io/style.h>
00041 #include <vfs/vfs.h>
00042 #include <stdarg.h>
00043 #include <stats.h>
00044 #include <inttypes.h>
00045 #include "screen.h"
00046 #include "top.h"
00047 
00048 static sysarg_t warn_col = 0;
00049 static sysarg_t warn_row = 0;
00050 
00051 static void screen_style_normal(void)
00052 {
00053         fflush(stdout);
00054         console_set_style(fphone(stdout), STYLE_NORMAL);
00055 }
00056 
00057 static void screen_style_inverted(void)
00058 {
00059         fflush(stdout);
00060         console_set_style(fphone(stdout), STYLE_INVERTED);
00061 }
00062 
00063 static void screen_moveto(sysarg_t col, sysarg_t row)
00064 {
00065         fflush(stdout);
00066         console_set_pos(fphone(stdout), col, row);
00067 }
00068 
00069 static void screen_get_pos(sysarg_t *col, sysarg_t *row)
00070 {
00071         fflush(stdout);
00072         console_get_pos(fphone(stdout), col, row);
00073 }
00074 
00075 static void screen_get_size(sysarg_t *col, sysarg_t *row)
00076 {
00077         fflush(stdout);
00078         console_get_size(fphone(stdout), col, row);
00079 }
00080 
00081 static void screen_restart(bool clear)
00082 {
00083         screen_style_normal();
00084         
00085         if (clear) {
00086                 fflush(stdout);
00087                 console_clear(fphone(stdout));
00088         }
00089         
00090         screen_moveto(0, 0);
00091 }
00092 
00093 static void screen_newline(void)
00094 {
00095         sysarg_t cols;
00096         sysarg_t rows;
00097         screen_get_size(&cols, &rows);
00098         
00099         sysarg_t c;
00100         sysarg_t r;
00101         screen_get_pos(&c, &r);
00102         
00103         sysarg_t i;
00104         for (i = c + 1; i < cols; i++)
00105                 puts(" ");
00106         
00107         if (r + 1 < rows)
00108                 puts("\n");
00109 }
00110 
00111 void screen_init(void)
00112 {
00113         fflush(stdout);
00114         console_cursor_visibility(fphone(stdout), false);
00115         
00116         screen_restart(true);
00117 }
00118 
00119 void screen_done(void)
00120 {
00121         screen_restart(true);
00122         
00123         fflush(stdout);
00124         console_cursor_visibility(fphone(stdout), true);
00125 }
00126 
00127 static void print_percent(fixed_float ffloat, unsigned int precision)
00128 {
00129         printf("%3" PRIu64 ".", ffloat.upper / ffloat.lower);
00130         
00131         unsigned int i;
00132         uint64_t rest = (ffloat.upper % ffloat.lower) * 10;
00133         for (i = 0; i < precision; i++) {
00134                 printf("%" PRIu64, rest / ffloat.lower);
00135                 rest = (rest % ffloat.lower) * 10;
00136         }
00137         
00138         printf("%%");
00139 }
00140 
00141 static void print_string(const char *str)
00142 {
00143         sysarg_t cols;
00144         sysarg_t rows;
00145         screen_get_size(&cols, &rows);
00146         
00147         sysarg_t c;
00148         sysarg_t r;
00149         screen_get_pos(&c, &r);
00150         
00151         if (c < cols) {
00152                 int pos = cols - c - 1;
00153                 printf("%.*s", pos, str);
00154         }
00155 }
00156 
00157 static inline void print_global_head(data_t *data)
00158 {
00159         printf("top - %02lu:%02lu:%02lu up "
00160             "%" PRIun " days, %02" PRIun ":%02" PRIun ":%02" PRIun ", "
00161             "load average:",
00162             data->hours, data->minutes, data->seconds,
00163             data->udays, data->uhours, data->uminutes, data->useconds);
00164         
00165         size_t i;
00166         for (i = 0; i < data->load_count; i++) {
00167                 puts(" ");
00168                 stats_print_load_fragment(data->load[i], 2);
00169         }
00170         
00171         screen_newline();
00172 }
00173 
00174 static inline void print_task_summary(data_t *data)
00175 {
00176         printf("tasks: %zu total", data->tasks_count);
00177         screen_newline();
00178 }
00179 
00180 static inline void print_thread_summary(data_t *data)
00181 {
00182         size_t total = 0;
00183         size_t running = 0;
00184         size_t ready = 0;
00185         size_t sleeping = 0;
00186         size_t lingering = 0;
00187         size_t other = 0;
00188         size_t invalid = 0;
00189         
00190         size_t i;
00191         for (i = 0; i < data->threads_count; i++) {
00192                 total++;
00193                 
00194                 switch (data->threads[i].state) {
00195                 case Running:
00196                         running++;
00197                         break;
00198                 case Ready:
00199                         ready++;
00200                         break;
00201                 case Sleeping:
00202                         sleeping++;
00203                         break;
00204                 case Lingering:
00205                         lingering++;
00206                         break;
00207                 case Entering:
00208                 case Exiting:
00209                         other++;
00210                         break;
00211                 default:
00212                         invalid++;
00213                 }
00214         }
00215         
00216         printf("threads: %zu total, %zu running, %zu ready, "
00217             "%zu sleeping, %zu lingering, %zu other, %zu invalid",
00218             total, running, ready, sleeping, lingering, other, invalid);
00219         screen_newline();
00220 }
00221 
00222 static inline void print_cpu_info(data_t *data)
00223 {
00224         size_t i;
00225         for (i = 0; i < data->cpus_count; i++) {
00226                 if (data->cpus[i].active) {
00227                         uint64_t busy;
00228                         uint64_t idle;
00229                         char busy_suffix;
00230                         char idle_suffix;
00231                         
00232                         order_suffix(data->cpus[i].busy_cycles, &busy, &busy_suffix);
00233                         order_suffix(data->cpus[i].idle_cycles, &idle, &idle_suffix);
00234                         
00235                         printf("cpu%u (%4" PRIu16 " MHz): busy cycles: "
00236                             "%" PRIu64 "%c, idle cycles: %" PRIu64 "%c",
00237                             data->cpus[i].id, data->cpus[i].frequency_mhz,
00238                             busy, busy_suffix, idle, idle_suffix);
00239                         puts(", idle: ");
00240                         print_percent(data->cpus_perc[i].idle, 2);
00241                         puts(", busy: ");
00242                         print_percent(data->cpus_perc[i].busy, 2);
00243                 } else
00244                         printf("cpu%u inactive", data->cpus[i].id);
00245                 
00246                 screen_newline();
00247         }
00248 }
00249 
00250 static inline void print_physmem_info(data_t *data)
00251 {
00252         uint64_t total;
00253         uint64_t unavail;
00254         uint64_t used;
00255         uint64_t free;
00256         const char *total_suffix;
00257         const char *unavail_suffix;
00258         const char *used_suffix;
00259         const char *free_suffix;
00260         
00261         bin_order_suffix(data->physmem->total, &total, &total_suffix, false);
00262         bin_order_suffix(data->physmem->unavail, &unavail, &unavail_suffix, false);
00263         bin_order_suffix(data->physmem->used, &used, &used_suffix, false);
00264         bin_order_suffix(data->physmem->free, &free, &free_suffix, false);
00265         
00266         printf("memory: %" PRIu64 "%s total, %" PRIu64 "%s unavail, %"
00267             PRIu64 "%s used, %" PRIu64 "%s free", total, total_suffix,
00268             unavail, unavail_suffix, used, used_suffix, free, free_suffix);
00269         screen_newline();
00270 }
00271 
00272 static inline void print_tasks_head(void)
00273 {
00274         screen_style_inverted();
00275         printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
00276             " [%%user] [%%kern] [name");
00277         screen_newline();
00278         screen_style_normal();
00279 }
00280 
00281 static inline void print_tasks(data_t *data)
00282 {
00283         sysarg_t cols;
00284         sysarg_t rows;
00285         screen_get_size(&cols, &rows);
00286         
00287         sysarg_t col;
00288         sysarg_t row;
00289         screen_get_pos(&col, &row);
00290         
00291         size_t i;
00292         for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
00293                 stats_task_t *task = data->tasks + data->tasks_map[i];
00294                 perc_task_t *perc = data->tasks_perc + data->tasks_map[i];
00295                 
00296                 uint64_t resmem;
00297                 const char *resmem_suffix;
00298                 bin_order_suffix(task->resmem, &resmem, &resmem_suffix, true);
00299                 
00300                 uint64_t virtmem;
00301                 const char *virtmem_suffix;
00302                 bin_order_suffix(task->virtmem, &virtmem, &virtmem_suffix, true);
00303                 
00304                 printf("%-8" PRIu64 " %7zu %7" PRIu64 "%s ",
00305                     task->task_id, task->threads, resmem, resmem_suffix);
00306                 print_percent(perc->resmem, 2);
00307                 printf(" %6" PRIu64 "%s ", virtmem, virtmem_suffix);
00308                 print_percent(perc->virtmem, 2);
00309                 puts(" ");
00310                 print_percent(perc->ucycles, 2);
00311                 puts(" ");
00312                 print_percent(perc->kcycles, 2);
00313                 puts(" ");
00314                 print_string(task->name);
00315                 
00316                 screen_newline();
00317         }
00318         
00319         while (row < rows) {
00320                 screen_newline();
00321                 row++;
00322         }
00323 }
00324 
00325 static inline void print_ipc_head(void)
00326 {
00327         screen_style_inverted();
00328         printf("[taskid] [cls snt] [cls rcv] [ans snt]"
00329             " [ans rcv] [irq rcv] [forward] [name");
00330         screen_newline();
00331         screen_style_normal();
00332 }
00333 
00334 static inline void print_ipc(data_t *data)
00335 {
00336         sysarg_t cols;
00337         sysarg_t rows;
00338         screen_get_size(&cols, &rows);
00339         
00340         sysarg_t col;
00341         sysarg_t row;
00342         screen_get_pos(&col, &row);
00343         
00344         size_t i;
00345         for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
00346                 uint64_t call_sent;
00347                 uint64_t call_received;
00348                 uint64_t answer_sent;
00349                 uint64_t answer_received;
00350                 uint64_t irq_notif_received;
00351                 uint64_t forwarded;
00352                 
00353                 char call_sent_suffix;
00354                 char call_received_suffix;
00355                 char answer_sent_suffix;
00356                 char answer_received_suffix;
00357                 char irq_notif_received_suffix;
00358                 char forwarded_suffix;
00359                 
00360                 order_suffix(data->tasks[i].ipc_info.call_sent, &call_sent,
00361                     &call_sent_suffix);
00362                 order_suffix(data->tasks[i].ipc_info.call_received,
00363                     &call_received, &call_received_suffix);
00364                 order_suffix(data->tasks[i].ipc_info.answer_sent,
00365                     &answer_sent, &answer_sent_suffix);
00366                 order_suffix(data->tasks[i].ipc_info.answer_received,
00367                     &answer_received, &answer_received_suffix);
00368                 order_suffix(data->tasks[i].ipc_info.irq_notif_received,
00369                     &irq_notif_received, &irq_notif_received_suffix);
00370                 order_suffix(data->tasks[i].ipc_info.forwarded, &forwarded,
00371                     &forwarded_suffix);
00372                 
00373                 printf("%-8" PRIu64 " %8" PRIu64 "%c %8" PRIu64 "%c"
00374                      " %8" PRIu64 "%c %8" PRIu64 "%c %8" PRIu64 "%c"
00375                      " %8" PRIu64 "%c ", data->tasks[i].task_id,
00376                      call_sent, call_sent_suffix,
00377                      call_received, call_received_suffix,
00378                      answer_sent, answer_sent_suffix,
00379                      answer_received, answer_received_suffix,
00380                      irq_notif_received, irq_notif_received_suffix,
00381                      forwarded, forwarded_suffix);
00382                 print_string(data->tasks[i].name);
00383                 
00384                 screen_newline();
00385         }
00386         
00387         while (row < rows) {
00388                 screen_newline();
00389                 row++;
00390         }
00391 }
00392 
00393 static inline void print_excs_head(void)
00394 {
00395         screen_style_inverted();
00396         printf("[exc   ] [count   ] [%%count] [cycles  ] [%%cycles] [description");
00397         screen_newline();
00398         screen_style_normal();
00399 }
00400 
00401 static inline void print_excs(data_t *data)
00402 {
00403         sysarg_t cols;
00404         sysarg_t rows;
00405         screen_get_size(&cols, &rows);
00406         
00407         sysarg_t col;
00408         sysarg_t row;
00409         screen_get_pos(&col, &row);
00410         
00411         size_t i;
00412         for (i = 0; (i < data->exceptions_count) && (row < rows); i++) {
00413                 /* Filter-out cold exceptions if not instructed otherwise */
00414                 if ((!excs_all) && (!data->exceptions[i].hot))
00415                         continue;
00416                 
00417                 uint64_t count;
00418                 uint64_t cycles;
00419                 
00420                 char count_suffix;
00421                 char cycles_suffix;
00422                 
00423                 order_suffix(data->exceptions[i].count, &count, &count_suffix);
00424                 order_suffix(data->exceptions[i].cycles, &cycles, &cycles_suffix);
00425                 
00426                 printf("%-8u %9" PRIu64 "%c  ",
00427                      data->exceptions[i].id, count, count_suffix);
00428                 print_percent(data->exceptions_perc[i].count, 2);
00429                 printf(" %9" PRIu64 "%c   ", cycles, cycles_suffix);
00430                 print_percent(data->exceptions_perc[i].cycles, 2);
00431                 puts(" ");
00432                 print_string(data->exceptions[i].desc);
00433                 
00434                 screen_newline();
00435                 row++;
00436         }
00437         
00438         while (row < rows) {
00439                 screen_newline();
00440                 row++;
00441         }
00442 }
00443 
00444 static void print_help(void)
00445 {
00446         sysarg_t cols;
00447         sysarg_t rows;
00448         screen_get_size(&cols, &rows);
00449         
00450         sysarg_t col;
00451         sysarg_t row;
00452         screen_get_pos(&col, &row);
00453         
00454         screen_newline();
00455         
00456         printf("Operation modes:");
00457         screen_newline();
00458         
00459         printf(" t .. tasks statistics");
00460         screen_newline();
00461         
00462         printf(" i .. IPC statistics");
00463         screen_newline();
00464         
00465         printf(" e .. exceptions statistics");
00466         screen_newline();
00467         
00468         printf("      a .. toggle display of all/hot exceptions");
00469         screen_newline();
00470         
00471         row += 6;
00472         
00473         while (row < rows) {
00474                 screen_newline();
00475                 row++;
00476         }
00477 }
00478 
00479 void print_data(data_t *data)
00480 {
00481         screen_restart(false);
00482         print_global_head(data);
00483         print_task_summary(data);
00484         print_thread_summary(data);
00485         print_cpu_info(data);
00486         print_physmem_info(data);
00487         
00488         /* Empty row for warnings */
00489         screen_get_pos(&warn_col, &warn_row);
00490         screen_newline();
00491         
00492         switch (op_mode) {
00493         case OP_TASKS:
00494                 print_tasks_head();
00495                 print_tasks(data);
00496                 break;
00497         case OP_IPC:
00498                 print_ipc_head();
00499                 print_ipc(data);
00500                 break;
00501         case OP_EXCS:
00502                 print_excs_head();
00503                 print_excs(data);
00504                 break;
00505         case OP_HELP:
00506                 print_tasks_head();
00507                 print_help();
00508         }
00509         
00510         fflush(stdout);
00511 }
00512 
00513 void print_warning(const char *fmt, ...)
00514 {
00515         screen_moveto(warn_col, warn_row);
00516         
00517         va_list args;
00518         va_start(args, fmt);
00519         vprintf(fmt, args);
00520         va_end(args);
00521         
00522         screen_newline();
00523         fflush(stdout);
00524 }
00525 

Generated on Thu Jun 2 07:45:43 2011 for HelenOS/USB by  doxygen 1.4.7