source: mainline/uspace/app/top/top.c@ 9dae191e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9dae191e was bdfd3c97, checked in by Stanislav Kozina <stanislav.kozina@…>, 15 years ago

Press 'i' in top and you can see IPC statistics.

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * Copyright (c) 2010 Stanislav Kozina
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup top
30 * @brief Top utility.
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <uptime.h>
41#include <task.h>
42#include <thread.h>
43#include <sys/time.h>
44#include <load.h>
45#include <ps.h>
46#include <arch/barrier.h>
47#include "screen.h"
48#include "input.h"
49#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
57
58int operation_type;
59
60static void read_data(data_t *target)
61{
62 /* Read current time */
63 struct timeval time;
64 if (gettimeofday(&time, NULL) != 0) {
65 printf("Cannot get time of day!\n");
66 exit(1);
67 }
68 target->hours = (time.tv_sec % DAY) / HOUR;
69 target->minutes = (time.tv_sec % HOUR) / MINUTE;
70 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);
94}
95
96/** Computes percentage differencies from old_data to new_data
97 *
98 * @param old_data Pointer to old data strucutre.
99 * @param new_data Pointer to actual data where percetages are stored.
100 *
101 */
102static void compute_percentages(data_t *old_data, data_t *new_data)
103{
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;
111 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
116 /* 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) {
128 /* This is newly borned task, ignore it */
129 ucycles_diff[i] = 0;
130 kcycles_diff[i] = 0;
131 continue;
132 }
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;
138 ucycles_total += ucycles_diff[i];
139 kcycles_total += kcycles_diff[i];
140 }
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 */
154 free(ucycles_diff);
155 free(kcycles_diff);
156}
157
158static void free_data(data_t *target)
159{
160 free(target->taskinfos);
161 free(target->thread_infos);
162 free(target->cpus);
163 free(target->cpu_perc);
164 free(target->task_perc);
165}
166
167static 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
175static data_t data[2];
176
177int main(int argc, char *argv[])
178{
179 data_t *data1 = &data[0];
180 data_t *data2 = &data[1];
181 screen_init();
182
183 /* Read initial stats */
184 printf("Reading initial data...\n");
185 read_data(data1);
186 /* Compute some rubbish to have initialised values */
187 compute_percentages(data1, data1);
188
189 /* And paint screen until death... */
190 operation_type = OP_TASKS;
191 while (true) {
192 char c = tgetchar(UPDATE_INTERVAL);
193 if (c < 0) {
194 read_data(data2);
195 compute_percentages(data1, data2);
196 free_data(data1);
197 print_data(data2);
198 swap(&data1, &data2);
199 continue;
200 }
201 switch (c) {
202 case 'q':
203 clear_screen();
204 return 0;
205 case 'i':
206 PRINT_WARNING("Showing IPC statistics", c);
207 operation_type = OP_IPC;
208 break;
209 case 't':
210 PRINT_WARNING("Showing task stats", c);
211 operation_type = OP_TASKS;
212 break;
213 default:
214 PRINT_WARNING("Unknown command: %c", c);
215 break;
216 }
217
218 }
219
220 free_data(data1);
221 free_data(data2);
222 return 0;
223}
224
225/** @}
226 */
Note: See TracBrowser for help on using the repository browser.