[18b5402c] | 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 |
|
---|
[da98918] | 29 | /** @addtogroup tasks
|
---|
[18b5402c] | 30 | * @brief Task lister.
|
---|
| 31 | * @{
|
---|
| 32 | */
|
---|
| 33 | /**
|
---|
| 34 | * @file
|
---|
| 35 | */
|
---|
| 36 |
|
---|
| 37 | #include <stdio.h>
|
---|
| 38 | #include <task.h>
|
---|
| 39 | #include <thread.h>
|
---|
[9dae191e] | 40 | #include <stats.h>
|
---|
[18b5402c] | 41 | #include <errno.h>
|
---|
| 42 | #include <stdlib.h>
|
---|
| 43 | #include <malloc.h>
|
---|
[9dae191e] | 44 | #include <inttypes.h>
|
---|
| 45 | #include <arg_parse.h>
|
---|
[ea55bc4] | 46 | #include "func.h"
|
---|
| 47 |
|
---|
[da98918] | 48 | #define NAME "tasks"
|
---|
[9dae191e] | 49 |
|
---|
| 50 | #define TASK_COUNT 10
|
---|
| 51 | #define THREAD_COUNT 50
|
---|
[18b5402c] | 52 |
|
---|
[9dae191e] | 53 | #define PRINT_LOAD1(x) ((x) >> 11)
|
---|
| 54 | #define PRINT_LOAD2(x) (((x) & 0x7ff) / 2)
|
---|
[9d491a7] | 55 |
|
---|
[34bba0e] | 56 | /** Thread states */
|
---|
[9dae191e] | 57 | //static const char *thread_states[] = {
|
---|
| 58 | // "Invalid",
|
---|
| 59 | // "Running",
|
---|
| 60 | // "Sleeping",
|
---|
| 61 | // "Ready",
|
---|
| 62 | // "Entering",
|
---|
| 63 | // "Exiting",
|
---|
| 64 | // "Lingering"
|
---|
| 65 | //};
|
---|
[34bba0e] | 66 |
|
---|
[18b5402c] | 67 | static void list_tasks(void)
|
---|
| 68 | {
|
---|
[9dae191e] | 69 | size_t count;
|
---|
| 70 | task_id_t *ids =
|
---|
| 71 | (task_id_t *) get_stats_tasks(&count);
|
---|
| 72 |
|
---|
| 73 | if (ids == NULL) {
|
---|
| 74 | fprintf(stderr, "%s: Unable to get tasks\n", NAME);
|
---|
| 75 | return;
|
---|
[18b5402c] | 76 | }
|
---|
[9dae191e] | 77 |
|
---|
| 78 | printf(" ID Threads Mem uCycles kCycles Name\n");
|
---|
| 79 |
|
---|
| 80 | size_t i;
|
---|
| 81 | for (i = 0; i < count; i++) {
|
---|
| 82 | stats_task_t *stats_task = get_stats_task(ids[i]);
|
---|
| 83 | if (stats_task != NULL) {
|
---|
| 84 | uint64_t virtmem, ucycles, kcycles;
|
---|
| 85 | char vmsuffix, usuffix, ksuffix;
|
---|
| 86 |
|
---|
| 87 | order(stats_task->virtmem, &virtmem, &vmsuffix);
|
---|
| 88 | order(stats_task->ucycles, &ucycles, &usuffix);
|
---|
| 89 | order(stats_task->kcycles, &kcycles, &ksuffix);
|
---|
| 90 |
|
---|
| 91 | printf("%8" PRIu64 "%8u %8" PRIu64"%c %12"
|
---|
| 92 | PRIu64"%c %12" PRIu64"%c %s\n", ids[i], stats_task->threads,
|
---|
| 93 | virtmem, vmsuffix, ucycles, usuffix, kcycles, ksuffix,
|
---|
| 94 | stats_task->name);
|
---|
| 95 |
|
---|
| 96 | free(stats_task);
|
---|
| 97 | } else
|
---|
| 98 | printf("%8" PRIu64 "\n", ids[i]);
|
---|
[18b5402c] | 99 | }
|
---|
[9dae191e] | 100 |
|
---|
| 101 | free(ids);
|
---|
[18b5402c] | 102 | }
|
---|
| 103 |
|
---|
[9dae191e] | 104 | static void list_threads(task_id_t task_id)
|
---|
[18b5402c] | 105 | {
|
---|
[9dae191e] | 106 | /* TODO:
|
---|
[638927a] | 107 | size_t thread_count = THREAD_COUNT;
|
---|
[18b5402c] | 108 | thread_info_t *threads = malloc(thread_count * sizeof(thread_info_t));
|
---|
[638927a] | 109 | size_t result = get_task_threads(threads, sizeof(thread_info_t) * thread_count);
|
---|
[18b5402c] | 110 |
|
---|
| 111 | while (result > thread_count) {
|
---|
| 112 | thread_count *= 2;
|
---|
| 113 | threads = realloc(threads, thread_count * sizeof(thread_info_t));
|
---|
[faf38b2] | 114 | result = get_task_threads(threads, sizeof(thread_info_t) * thread_count);
|
---|
[18b5402c] | 115 | }
|
---|
| 116 |
|
---|
[34bba0e] | 117 | if (result == 0) {
|
---|
| 118 | printf("No task with given pid!\n");
|
---|
| 119 | exit(1);
|
---|
| 120 | }
|
---|
| 121 |
|
---|
[638927a] | 122 | size_t i;
|
---|
[ea55bc4] | 123 | printf(" ID State CPU Prio [k]uCycles [k]kcycles Cycle fault\n");
|
---|
[18b5402c] | 124 | for (i = 0; i < result; ++i) {
|
---|
[faf38b2] | 125 | if (threads[i].taskid != taskid) {
|
---|
| 126 | continue;
|
---|
| 127 | }
|
---|
[1ba37fa] | 128 | uint64_t ucycles, kcycles;
|
---|
| 129 | char usuffix, ksuffix;
|
---|
[ea55bc4] | 130 | order(threads[i].ucycles, &ucycles, &usuffix);
|
---|
| 131 | order(threads[i].kcycles, &kcycles, &ksuffix);
|
---|
[1ba37fa] | 132 | printf("%6llu %-8s %4u %6d %12llu%c %12llu%c\n", threads[i].tid,
|
---|
[07640dfd] | 133 | thread_states[threads[i].state], threads[i].cpu,
|
---|
[ea55bc4] | 134 | threads[i].priority, ucycles, usuffix,
|
---|
[1ba37fa] | 135 | kcycles, ksuffix);
|
---|
[18b5402c] | 136 | }
|
---|
[83a957a] | 137 |
|
---|
[9dae191e] | 138 | free(threads); */
|
---|
[18b5402c] | 139 | }
|
---|
| 140 |
|
---|
[9dae191e] | 141 | static void print_load(void)
|
---|
[944f2cab] | 142 | {
|
---|
[9dae191e] | 143 | size_t count;
|
---|
| 144 | load_t *load = get_stats_load(&count);
|
---|
| 145 |
|
---|
| 146 | if (load == NULL) {
|
---|
| 147 | fprintf(stderr, "%s: Unable to get load\n", NAME);
|
---|
| 148 | return;
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | printf("%s: Load avarage: ", NAME);
|
---|
| 152 |
|
---|
| 153 | size_t i;
|
---|
| 154 | for (i = 0; i < count; i++) {
|
---|
| 155 | if (i > 0)
|
---|
| 156 | printf(" ");
|
---|
| 157 |
|
---|
| 158 | print_load_fragment(load[i], 2);
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 | printf("\n");
|
---|
| 162 |
|
---|
| 163 | free(load);
|
---|
[944f2cab] | 164 | }
|
---|
| 165 |
|
---|
[9dae191e] | 166 | static void list_cpus(void)
|
---|
[62550dce] | 167 | {
|
---|
[9dae191e] | 168 | size_t count;
|
---|
| 169 | stats_cpu_t *cpus = get_stats_cpus(&count);
|
---|
| 170 |
|
---|
| 171 | if (cpus == NULL) {
|
---|
| 172 | fprintf(stderr, "%s: Unable to get CPU statistics\n", NAME);
|
---|
| 173 | return;
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 | printf("%s: %u CPU(s) detected\n", NAME, count);
|
---|
| 177 |
|
---|
[62550dce] | 178 | size_t i;
|
---|
[9dae191e] | 179 | for (i = 0; i < count; i++) {
|
---|
| 180 | printf("cpu%u: %" PRIu16 " MHz, busy ticks: "
|
---|
| 181 | "%" PRIu64 ", idle ticks: %" PRIu64 "\n",
|
---|
| 182 | cpus[i].id, cpus[i].frequency_mhz, cpus[i].busy_ticks,
|
---|
| 183 | cpus[i].idle_ticks);
|
---|
[62550dce] | 184 | }
|
---|
[9dae191e] | 185 |
|
---|
| 186 | free(cpus);
|
---|
[62550dce] | 187 | }
|
---|
| 188 |
|
---|
[34bba0e] | 189 | static void usage()
|
---|
| 190 | {
|
---|
[9dae191e] | 191 | printf(
|
---|
[da98918] | 192 | "Usage: tasks [-t task_id] [-l] [-c]\n" \
|
---|
[9dae191e] | 193 | "\n" \
|
---|
| 194 | "Options:\n" \
|
---|
| 195 | "\t-t task_id\n" \
|
---|
| 196 | "\t--task=task_id\n" \
|
---|
| 197 | "\t\tList threads of the given task\n" \
|
---|
| 198 | "\n" \
|
---|
| 199 | "\t-l\n" \
|
---|
| 200 | "\t--load\n" \
|
---|
| 201 | "\t\tPrint system load\n" \
|
---|
| 202 | "\n" \
|
---|
| 203 | "\t-c\n" \
|
---|
| 204 | "\t--cpu\n" \
|
---|
| 205 | "\t\tList CPUs\n" \
|
---|
| 206 | "\n" \
|
---|
| 207 | "\t-h\n" \
|
---|
| 208 | "\t--help\n" \
|
---|
| 209 | "\t\tPrint this usage information\n"
|
---|
| 210 | "\n" \
|
---|
| 211 | "Without any options all tasks are listed\n"
|
---|
| 212 | );
|
---|
[34bba0e] | 213 | }
|
---|
| 214 |
|
---|
[18b5402c] | 215 | int main(int argc, char *argv[])
|
---|
| 216 | {
|
---|
[9dae191e] | 217 | bool toggle_tasks = true;
|
---|
| 218 | bool toggle_threads = false;
|
---|
| 219 | bool toggle_load = false;
|
---|
| 220 | bool toggle_cpus = false;
|
---|
| 221 |
|
---|
| 222 | task_id_t task_id;
|
---|
| 223 |
|
---|
| 224 | int i;
|
---|
| 225 | for (i = 1; i < argc; i++) {
|
---|
| 226 | int off;
|
---|
| 227 |
|
---|
| 228 | /* Usage */
|
---|
| 229 | if ((off = arg_parse_short_long(argv[i], "-h", "--help")) != -1) {
|
---|
[34bba0e] | 230 | usage();
|
---|
[9dae191e] | 231 | return 0;
|
---|
| 232 | }
|
---|
| 233 |
|
---|
| 234 | /* Load */
|
---|
| 235 | if ((off = arg_parse_short_long(argv[i], "-l", "--load")) != -1) {
|
---|
| 236 | toggle_tasks = false;
|
---|
| 237 | toggle_load = true;
|
---|
| 238 | continue;
|
---|
| 239 | }
|
---|
| 240 |
|
---|
| 241 | /* CPUs */
|
---|
| 242 | if ((off = arg_parse_short_long(argv[i], "-c", "--cpus")) != -1) {
|
---|
| 243 | toggle_tasks = false;
|
---|
| 244 | toggle_cpus = true;
|
---|
| 245 | continue;
|
---|
| 246 | }
|
---|
| 247 |
|
---|
| 248 | /* Threads */
|
---|
| 249 | if ((off = arg_parse_short_long(argv[i], "-t", "--task=")) != -1) {
|
---|
| 250 | // TODO: Support for 64b range
|
---|
| 251 | int tmp;
|
---|
| 252 | int ret = arg_parse_int(argc, argv, &i, &tmp, off);
|
---|
| 253 | if (ret != EOK) {
|
---|
| 254 | printf("%s: Malformed task_id '%s'\n", NAME, argv[i]);
|
---|
| 255 | return -1;
|
---|
| 256 | }
|
---|
| 257 |
|
---|
| 258 | task_id = tmp;
|
---|
| 259 |
|
---|
| 260 | toggle_tasks = false;
|
---|
| 261 | toggle_threads = true;
|
---|
| 262 | continue;
|
---|
[18b5402c] | 263 | }
|
---|
| 264 | }
|
---|
[9dae191e] | 265 |
|
---|
| 266 | if (toggle_tasks)
|
---|
| 267 | list_tasks();
|
---|
| 268 |
|
---|
| 269 | if (toggle_threads)
|
---|
| 270 | list_threads(task_id);
|
---|
| 271 |
|
---|
| 272 | if (toggle_load)
|
---|
| 273 | print_load();
|
---|
| 274 |
|
---|
| 275 | if (toggle_cpus)
|
---|
| 276 | list_cpus();
|
---|
| 277 |
|
---|
[18b5402c] | 278 | return 0;
|
---|
| 279 | }
|
---|
| 280 |
|
---|
| 281 | /** @}
|
---|
| 282 | */
|
---|