This patchset introduce a tree structure to store information found in the different directories we are looking for the power management.
The code clock has been replaced by a new code based on this tree.
The result is a code modular and generic enough to be used for the other power management blocks and to add more blocks like the gpio and the thermal framework.
The patch 'rewrite the powerdebug clock code' has been folded in a single one because it was too hard to review the patchset itself.
The display code has been reworked to be generic too but it is still focused on the clock display for the moment.
The following bugs were fixed too: * https://bugs.launchpad.net/linaro-pm-wg/+bug/794725 * https://bugs.launchpad.net/linaro-pm-wg/+bug/794726 * https://bugs.launchpad.net/linaro-pm-wg/+bug/794728 * https://bugs.launchpad.net/linaro-pm-wg/+bug/794731
The drawback is the find clock interface is broken so it is disabled for the moment. It will be enabled again with the next patchset coming next week.
Daniel Lezcano (23): move clock_info structure definition reorganize code to prevent forward declaration provide a clock allocator remove unused variable fix segfault when the default window is not the clock refresh the windows instead of killing them and recreate tree structure abstraction for directory hierarchies function helper to read the files use the tree code to dump the clocks Remove old clock tree dump code add 'find' function for the tree use 'find' tree function remove unused parameter remove unused parameter 'options->dump' remove unused code and parameter for clock dump function remove unused 'verbose' option add a function to browse at reverse order the tree make the mainloop immune against the signals add a tree function to return a list of elements compute the number of children for a specific node document the tree code rewrite the powerdebug clock code remove unused 'hrow' and 'selected' parameters
Makefile | 2 +- clocks.c | 639 ++++++++++++++++++++++++---------------------------------- clocks.h | 13 -- display.c | 229 +++++++++++++++------- powerdebug.c | 90 +++++---- powerdebug.h | 26 ++- tree.c | 353 ++++++++++++++++++++++++++++++++ tree.h | 54 +++++ 8 files changed, 890 insertions(+), 516 deletions(-) create mode 100644 tree.c create mode 100644 tree.h
Let's make this structure private
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 13 +++++++++++++ clocks.h | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/clocks.c b/clocks.c index 3a93421..4d8a2be 100644 --- a/clocks.c +++ b/clocks.c @@ -28,6 +28,19 @@ static char clock_lines[MAX_LINES][128]; static int clock_line_no; static int old_clock_line_no;
+struct clock_info { + char name[NAME_MAX]; + int flags; + int rate; + int usecount; + int num_children; + int last_child; + int expanded; + int level; + struct clock_info *parent; + struct clock_info **children; +} *clocks_info; + static int locate_debugfs(char *clk_path) { const char *mtab = "/proc/mounts"; diff --git a/clocks.h b/clocks.h index 9ad9804..d66c061 100644 --- a/clocks.h +++ b/clocks.h @@ -15,17 +15,4 @@
extern int maxy;
-struct clock_info { - char name[NAME_MAX]; - int flags; - int rate; - int usecount; - int num_children; - int last_child; - int expanded; - int level; - struct clock_info *parent; - struct clock_info **children; -} *clocks_info; - extern int clock_init(void);
That will cleanup the powerdebug header because these functions are used in the clock code only.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 142 +++++++++++++++++++++++++++++----------------------------- powerdebug.h | 4 -- 2 files changed, 71 insertions(+), 75 deletions(-)
diff --git a/clocks.c b/clocks.c index 4d8a2be..677db01 100644 --- a/clocks.c +++ b/clocks.c @@ -372,63 +372,28 @@ void print_clock_info(int verbose, int hrow, int selected) clock_line_no = 0; }
-void read_and_dump_clock_info_one(char *clk, bool dump) -{ - printf("\nParents for "%s" Clock :\n\n", clk); - read_clock_info(clk_dir_path); - dump_all_parents(clk, dump); - printf("\n\n"); -} - -void read_and_dump_clock_info(int verbose) -{ - (void)verbose; - printf("\nClock Tree :\n"); - printf("**********\n"); - read_clock_info(clk_dir_path); - dump_clock_info(clocks_info, 1, 1); - printf("\n\n"); -} - -void read_clock_info(char *clkpath) +static void insert_children(struct clock_info **parent, struct clock_info *clk) { - DIR *dir; - struct dirent *item; - char filename[NAME_MAX], clockname[NAME_MAX]; - struct clock_info *child; - struct clock_info *cur; - - dir = opendir(clkpath); - if (!dir) - return; - - clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info)); - memset(clocks_info, 0, sizeof(clocks_info)); - strcpy(clocks_info->name, "/"); - clocks_info->level = 0; - - while ((item = readdir(dir))) { - /* skip hidden dirs except ".." */ - if (item->d_name[0] == '.') - continue; - - strcpy(clockname, item->d_name); - sprintf(filename, "%s/%s", clkpath, item->d_name); - cur = (struct clock_info *)malloc(sizeof(struct clock_info)); - memset(cur, 0, sizeof(struct clock_info)); - strcpy(cur->name, clockname); - cur->parent = clocks_info; - cur->num_children = 0; - cur->expanded = 0; - cur->level = 1; - insert_children(&clocks_info, cur); - child = read_clock_info_recur(filename, 2, cur); - } - closedir(dir); + if (!(*parent)->num_children || (*parent)->children == NULL) { + (*parent)->children = (struct clock_info **) + malloc(sizeof(struct clock_info *)*2); + (*parent)->num_children = 0; + } else + (*parent)->children = (struct clock_info **) + realloc((*parent)->children, + sizeof(struct clock_info *) * + ((*parent)->num_children + 2)); + if ((*parent)->num_children > 0) + (*parent)->children[(*parent)->num_children - 1]->last_child + = 0; + clk->last_child = 1; + (*parent)->children[(*parent)->num_children] = clk; + (*parent)->children[(*parent)->num_children + 1] = NULL; + (*parent)->num_children++; }
-struct clock_info *read_clock_info_recur(char *clkpath, int level, - struct clock_info *parent) +static struct clock_info *read_clock_info_recur(char *clkpath, int level, + struct clock_info *parent) { int ret = 0; DIR *dir; @@ -486,24 +451,49 @@ struct clock_info *read_clock_info_recur(char *clkpath, int level, return cur; }
-void insert_children(struct clock_info **parent, struct clock_info *clk) +void read_clock_info(char *clkpath) { - if (!(*parent)->num_children || (*parent)->children == NULL) { - (*parent)->children = (struct clock_info **) - malloc(sizeof(struct clock_info *)*2); - (*parent)->num_children = 0; - } else - (*parent)->children = (struct clock_info **) - realloc((*parent)->children, - sizeof(struct clock_info *) * - ((*parent)->num_children + 2)); - if ((*parent)->num_children > 0) - (*parent)->children[(*parent)->num_children - 1]->last_child - = 0; - clk->last_child = 1; - (*parent)->children[(*parent)->num_children] = clk; - (*parent)->children[(*parent)->num_children + 1] = NULL; - (*parent)->num_children++; + DIR *dir; + struct dirent *item; + char filename[NAME_MAX], clockname[NAME_MAX]; + struct clock_info *child; + struct clock_info *cur; + + dir = opendir(clkpath); + if (!dir) + return; + + clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info)); + memset(clocks_info, 0, sizeof(clocks_info)); + strcpy(clocks_info->name, "/"); + clocks_info->level = 0; + + while ((item = readdir(dir))) { + /* skip hidden dirs except ".." */ + if (item->d_name[0] == '.') + continue; + + strcpy(clockname, item->d_name); + sprintf(filename, "%s/%s", clkpath, item->d_name); + cur = (struct clock_info *)malloc(sizeof(struct clock_info)); + memset(cur, 0, sizeof(struct clock_info)); + strcpy(cur->name, clockname); + cur->parent = clocks_info; + cur->num_children = 0; + cur->expanded = 0; + cur->level = 1; + insert_children(&clocks_info, cur); + child = read_clock_info_recur(filename, 2, cur); + } + closedir(dir); +} + +void read_and_dump_clock_info_one(char *clk, bool dump) +{ + printf("\nParents for "%s" Clock :\n\n", clk); + read_clock_info(clk_dir_path); + dump_all_parents(clk, dump); + printf("\n\n"); }
void dump_clock_info(struct clock_info *clk, int level, int bmp) @@ -560,3 +550,13 @@ void dump_clock_info(struct clock_info *clk, int level, int bmp) } } } + +void read_and_dump_clock_info(int verbose) +{ + (void)verbose; + printf("\nClock Tree :\n"); + printf("**********\n"); + read_clock_info(clk_dir_path); + dump_clock_info(clocks_info, 1, 1); + printf("\n\n"); +} diff --git a/powerdebug.h b/powerdebug.h index a122b7f..1018998 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -31,10 +31,6 @@ enum {CLOCK_SELECTED = 1, REFRESH_WINDOW}; extern void read_and_dump_clock_info(int verbose); extern void read_and_dump_clock_info_one(char *clk, bool dump); extern void read_clock_info(char *clkpath); -extern struct clock_info *read_clock_info_recur(char *clkpath, int level, - struct clock_info *parent); -extern void dump_clock_info(struct clock_info *clk, int level, int bmp); -extern void insert_children(struct clock_info **parent, struct clock_info *clk); extern void find_parents_for_clock(char *clkname, int complete); extern int read_and_print_clock_info(int verbose, int hrow, int selected); extern void print_clock_info(int verbose, int hrow, int selected);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 43 ++++++++++++++++++++++++++++++++----------- powerdebug.h | 2 +- 2 files changed, 33 insertions(+), 12 deletions(-)
diff --git a/clocks.c b/clocks.c index 677db01..d08c926 100644 --- a/clocks.c +++ b/clocks.c @@ -451,33 +451,48 @@ static struct clock_info *read_clock_info_recur(char *clkpath, int level, return cur; }
-void read_clock_info(char *clkpath) +static struct clock_info *clock_alloc(const char *name) +{ + struct clock_info *ci; + + ci = malloc(sizeof(*ci)); + if (ci) { + memset(ci, 0, sizeof(*ci)); + strcpy(ci->name, name); + } + + return ci; +} + +int read_clock_info(char *clkpath) { DIR *dir; struct dirent *item; - char filename[NAME_MAX], clockname[NAME_MAX]; + char filename[NAME_MAX]; struct clock_info *child; struct clock_info *cur; + int ret = -1;
dir = opendir(clkpath); if (!dir) - return; + return -1;
- clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info)); - memset(clocks_info, 0, sizeof(clocks_info)); - strcpy(clocks_info->name, "/"); - clocks_info->level = 0; + clocks_info = clock_alloc("/"); + if (!clocks_info) + return -1;
while ((item = readdir(dir))) { + /* skip hidden dirs except ".." */ if (item->d_name[0] == '.') continue;
- strcpy(clockname, item->d_name); sprintf(filename, "%s/%s", clkpath, item->d_name); - cur = (struct clock_info *)malloc(sizeof(struct clock_info)); - memset(cur, 0, sizeof(struct clock_info)); - strcpy(cur->name, clockname); + + cur = clock_alloc(item->d_name); + if (!cur) + goto out; + cur->parent = clocks_info; cur->num_children = 0; cur->expanded = 0; @@ -485,7 +500,13 @@ void read_clock_info(char *clkpath) insert_children(&clocks_info, cur); child = read_clock_info_recur(filename, 2, cur); } + + ret = 0; + +out: closedir(dir); + + return ret; }
void read_and_dump_clock_info_one(char *clk, bool dump) diff --git a/powerdebug.h b/powerdebug.h index 1018998..0d8e8d1 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -30,7 +30,7 @@ enum {CLOCK_SELECTED = 1, REFRESH_WINDOW};
extern void read_and_dump_clock_info(int verbose); extern void read_and_dump_clock_info_one(char *clk, bool dump); -extern void read_clock_info(char *clkpath); +extern int read_clock_info(char *clkpath); extern void find_parents_for_clock(char *clkname, int complete); extern int read_and_print_clock_info(int verbose, int hrow, int selected); extern void print_clock_info(int verbose, int hrow, int selected);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- display.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/display.c b/display.c index 2d63908..2ab2167 100644 --- a/display.c +++ b/display.c @@ -34,11 +34,10 @@ static WINDOW *header_win; static WINDOW *regulator_win; static WINDOW *clock_win; static WINDOW *sensor_win; -static WINDOW *selected_win; static WINDOW *footer_win;
int maxx, maxy; -char footer_items[NUM_FOOTER_ITEMS][64]; +static char footer_items[NUM_FOOTER_ITEMS][64];
static char *win_names[TOTAL_FEATURE_WINS] = { "Clocks", @@ -149,8 +148,6 @@ void create_selectedwindow(int selectedwindow) break; }
- selected_win = win; - refresh(); }
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 2 +- powerdebug.c | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/clocks.c b/clocks.c index d08c926..ecc72ea 100644 --- a/clocks.c +++ b/clocks.c @@ -255,7 +255,7 @@ int read_and_print_clock_info(int verbose, int hrow, int selected) read_clock_info(clk_dir_path); }
- if (!clocks_info->num_children) { + if (!clocks_info || !clocks_info->num_children) { fprintf(stderr, "powerdebug: No clocks found. Exiting..\n"); exit(1); } diff --git a/powerdebug.c b/powerdebug.c index 5fe07de..94dd31a 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -251,19 +251,18 @@ int mainloop(struct powerdebug_options *options,
create_windows(options->selectedwindow); show_header(options->selectedwindow); + create_selectedwindow(options->selectedwindow);
- if (options->regulators || options->selectedwindow == REGULATOR) { + if (options->selectedwindow == REGULATOR) { regulator_read_info(reg_info, nr_reg); - create_selectedwindow(options->selectedwindow); show_regulator_info(reg_info, nr_reg, options->verbose); }
- if (options->clocks || options->selectedwindow == CLOCK) { + if (options->selectedwindow == CLOCK) {
int hrow;
- create_selectedwindow(options->selectedwindow); if (!findparent_ncurses) { int command = 0;
@@ -282,10 +281,8 @@ int mainloop(struct powerdebug_options *options, enter_hit); }
- if (options->sensors || options->selectedwindow == SENSOR) { - create_selectedwindow(options->selectedwindow); + if (options->selectedwindow == SENSOR) print_sensor_header(); - }
FD_ZERO(&readfds); FD_SET(0, &readfds);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- display.c | 74 +++++++++++++++++++++++---------------------------------- powerdebug.c | 2 +- 2 files changed, 31 insertions(+), 45 deletions(-)
diff --git a/display.c b/display.c index 2ab2167..dd5543c 100644 --- a/display.c +++ b/display.c @@ -45,31 +45,6 @@ static char *win_names[TOTAL_FEATURE_WINS] = { "Sensors" };
-/* "all" : Kill header and footer windows too ? */ -void killall_windows(int all) -{ - if (all && header_win) { - delwin(header_win); - header_win = NULL; - } - if (regulator_win) { - delwin(regulator_win); - regulator_win = NULL; - } - if (clock_win) { - delwin(clock_win); - clock_win = NULL; - } - if (sensor_win) { - delwin(sensor_win); - sensor_win = NULL; - } - if (all && footer_win) { - delwin(footer_win); - footer_win = NULL; - } -} - static void display_fini(void) { endwin(); @@ -99,18 +74,36 @@ int display_init(void) init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED)) return -1;
- return atexit(display_fini); -} - -void create_windows(int selectedwindow) -{ + if (atexit(display_fini)) + return -1;
getmaxyx(stdscr, maxy, maxx); - killall_windows(1); + + regulator_win = subwin(stdscr, maxy - 2, maxx, 1, 0); + if (!regulator_win) + return -1; + + clock_win = subwin(stdscr, maxy - 2, maxx, 1, 0); + if (!clock_win) + return -1; + + sensor_win = subwin(stdscr, maxy - 2, maxx, 1, 0); + if (!sensor_win) + return -1;
header_win = subwin(stdscr, 1, maxx, 0, 0); + if (!header_win) + return -1; + footer_win = subwin(stdscr, 1, maxx, maxy-1, 0); + if (!footer_win) + return -1; + + return 0; +}
+void create_windows(int selectedwindow) +{ strcpy(footer_items[0], " Q (Quit) "); strcpy(footer_items[1], " R (Refresh) ");
@@ -129,26 +122,19 @@ void create_windows(int selectedwindow)
void create_selectedwindow(int selectedwindow) { - WINDOW *win; - - killall_windows(0); - - getmaxyx(stdscr, maxy, maxx); - - win = subwin(stdscr, maxy - 2, maxx, 1, 0); - switch (selectedwindow) { - case REGULATOR: regulator_win = win; + case REGULATOR: + wrefresh(regulator_win); break;
- case CLOCK: clock_win = win; + case CLOCK: + wrefresh(clock_win); break;
- case SENSOR: sensor_win = win; + case SENSOR: + wrefresh(sensor_win); break; } - - refresh(); }
void show_header(int selectedwindow) diff --git a/powerdebug.c b/powerdebug.c index 94dd31a..af8d28c 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -215,7 +215,7 @@ int keystroke_callback(bool *enter_hit, bool *findparent_ncurses, keychar = toupper(keystroke); //#define DEBUG #ifdef DEBUG - killall_windows(1); fini_curses(); + fini_curses(); printf("key entered %d:%c\n", keystroke, keychar); exit(1); #endif
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- Makefile | 2 +- clocks.c | 7 ++ tree.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tree.h | 45 ++++++++++++ 4 files changed, 278 insertions(+), 1 deletions(-) create mode 100644 tree.c create mode 100644 tree.h
diff --git a/Makefile b/Makefile index 295b7cb..d88b8ff 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ MANDIR=/usr/share/man/man8 CFLAGS?=-O1 -g -Wall -Wshadow CC?=gcc
-OBJS = powerdebug.o sensor.o clocks.o regulator.o display.o +OBJS = powerdebug.o sensor.o clocks.o regulator.o display.o tree.o
default: powerdebug
diff --git a/clocks.c b/clocks.c index ecc72ea..8a2dc97 100644 --- a/clocks.c +++ b/clocks.c @@ -19,6 +19,7 @@
#include "powerdebug.h" #include "clocks.h" +#include "tree.h"
#define MAX_LINES 120
@@ -41,6 +42,8 @@ struct clock_info { struct clock_info **children; } *clocks_info;
+static struct tree *clock_tree; + static int locate_debugfs(char *clk_path) { const char *mtab = "/proc/mounts"; @@ -73,6 +76,10 @@ int clock_init(void)
sprintf(clk_dir_path, "%s/clock", clk_dir_path);
+ clock_tree = tree_load(clk_dir_path, NULL); + if (!clock_tree) + return -1; + return access(clk_dir_path, F_OK); }
diff --git a/tree.c b/tree.c new file mode 100644 index 0000000..e681f4f --- /dev/null +++ b/tree.c @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (C) 2010, Linaro Limited. + * + * This file is part of PowerDebug. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Author: + * Daniel Lezcano daniel.lezcano@linaro.org + * + *******************************************************************************/ + +#define _GNU_SOURCE +#include <stdio.h> +#undef _GNU_SOURCE +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "tree.h" + +/* + * Allocate a tree structure and initialize the different fields. + * + * @path : the absolute path to the directory + * @depth : the depth in the tree + * Returns a tree structure on success, NULL otherwise + */ +static inline struct tree *tree_alloc(const char *path, int depth) +{ + struct tree *t; + + t = malloc(sizeof(*t)); + if (!t) + return NULL; + + /* Full pathname */ + t->path = strdup(path); + if (!t->path) { + free(t); + return NULL; + } + + /* Basename pointer on the full path name */ + t->name = strrchr(t->path, '/') + 1; + + t->depth = depth; + t->tail = t; + t->child = NULL; + t->parent = NULL; + t->next = NULL; + t->prev = NULL; + t->private = NULL; + + return t; +} + +/* + * Free a tree structure and the fields we allocated in the + * tree_alloc function. + * + * @t : the tree structure to be freed + */ +static inline void tree_free(struct tree *t) +{ + free(t->path); + free(t); +} + +/* + * Add at the end of the list the new list element. + * + * @head : the list to be appened + * @new : the new element to be added at the end of the list + */ +static inline void tree_add_tail(struct tree *head, struct tree *new) +{ + new->prev = head->tail; + head->tail->next = new; + head->tail = new; +} + +/* + * Add a child in to a parent list, at the end of this list. + * + * @parent : the parent list to add the child + * @child : the child to be added + */ +static inline void tree_add_child(struct tree *parent, struct tree *child) +{ + child->parent = parent; + + if (parent->child) + return tree_add_tail(parent->child, child); + + parent->child = child; +} + +/* + * This function will browse the directory structure and build a + * tree reflecting the content of the directory tree. + * + * @tree : the root node of the tree + * @filter : a callback to filter out the directories + * Returns 0 on success, -1 otherwise + */ +static int tree_scan(struct tree *tree, tree_filter_t filter) +{ + DIR *dir; + char *basedir, *newpath; + struct dirent dirent, *direntp; + struct stat s; + int ret = 0; + + dir = opendir(tree->path); + if (!dir) + return -1; + + while (!readdir_r(dir, &dirent, &direntp)) { + + struct tree *child; + + if (!direntp) + break; + + if (direntp->d_name[0] == '.') + continue; + + if (filter && filter(direntp->d_name)) + continue; + + ret = asprintf(&basedir, "%s", tree->path); + if (ret < 0) + return -1; + + ret = basename(basedir) ? 0 : -1; + if (ret < 0) + goto out_free_basedir; + + ret = asprintf(&newpath, "%s/%s", basedir, direntp->d_name); + if (ret < 0) + goto out_free_basedir; + + ret = stat(newpath, &s); + if (ret) + goto out_free_newpath; + + if (S_ISDIR(s.st_mode)) { + + ret = -1; + + child = tree_alloc(newpath, tree->depth + 1); + if (!child) + goto out_free_newpath; + + tree_add_child(tree, child); + + ret = tree_scan(child, filter); + } + + out_free_newpath: + free(newpath); + + out_free_basedir: + free(basedir); + + if (ret) + break; + } + + closedir(dir); + + return ret; +} + +/* + * This function takes the topmost directory path and populate the + * directory tree structures. + * + * @tree : a path to the topmost directory path + * Returns a tree structure corresponding to the root node of the + * directory tree representation on success, NULL otherwise + */ +struct tree *tree_load(const char *path, tree_filter_t filter) +{ + struct tree *tree; + + tree = tree_alloc(path, 0); + if (!tree) + return NULL; + + if (tree_scan(tree, filter)) { + tree_free(tree); + return NULL; + } + + return tree; +} + +/* + * This function will go over the tree passed as parameter and + * will call the callback passed as parameter for each node. + * + * @tree : the topmost node where we begin to browse the tree + * Returns 0 on success, < 0 otherwise + */ +int tree_for_each(struct tree *tree, tree_cb_t cb, void *data) +{ + if (!tree) + return 0; + + if (cb(tree, data)) + return -1; + + if (tree_for_each(tree->child, cb, data)) + return -1; + + return tree_for_each(tree->next, cb, data); +} diff --git a/tree.h b/tree.h new file mode 100644 index 0000000..57c70f8 --- /dev/null +++ b/tree.h @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (C) 2010, Linaro Limited. + * + * This file is part of PowerDebug. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Author: + * Daniel Lezcano daniel.lezcano@linaro.org + * + *******************************************************************************/ + +/* + * Structure describing a node of the clock tree + * + * tail : points to the last element in the list + * next : points to the next element in the list + * child : points to the child node + * parent : points to the parent node + * depth : the recursive level of the node + * path : absolute pathname of the directory + * name : basename of the directory + */ +struct tree { + struct tree *tail; + struct tree *next; + struct tree *prev; + struct tree *child; + struct tree *parent; + char *path; + char *name; + void *private; + unsigned char depth; +}; + +typedef int (*tree_cb_t)(struct tree *t, void *data); + +typedef int (*tree_filter_t)(const char *name); + +extern struct tree *tree_load(const char *path, tree_filter_t filter); + +extern int tree_for_each(struct tree *tree, tree_cb_t cb, void *data);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/clocks.c b/clocks.c index 8a2dc97..848c52e 100644 --- a/clocks.c +++ b/clocks.c @@ -13,7 +13,11 @@ * - initial API and implementation *******************************************************************************/
+#ifndef _GNU_SOURCE +#define _GNU_SOURCE #include <stdio.h> +#undef _GNU_SOURCE +#endif #include <mntent.h> #include <sys/stat.h>
@@ -83,6 +87,42 @@ int clock_init(void) return access(clk_dir_path, F_OK); }
+/* + * This functions is a helper to read a specific file content and store + * the content inside a variable pointer passed as parameter, the format + * parameter gives the variable type to be read from the file. + * + * @path : directory path containing the file + * @name : name of the file to be read + * @format : the format of the format + * @value : a pointer to a variable to store the content of the file + * Returns 0 on success, -1 otherwise + */ +int file_read_value(const char *path, const char *name, + const char *format, void *value) +{ + FILE *file; + char *rpath; + int ret; + + ret = asprintf(&rpath, "%s/%s", path, name); + if (ret < 0) + return ret; + + file = fopen(rpath, "r"); + if (!file) { + ret = -1; + goto out_free; + } + + ret = fscanf(file, format, value) == EOF ? -1 : 0; + + fclose(file); +out_free: + free(rpath); + return ret; +} + static int file_read_from_format(char *file, int *value, const char *format) { FILE *f;
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/clocks.c b/clocks.c index 848c52e..5bb04a4 100644 --- a/clocks.c +++ b/clocks.c @@ -42,11 +42,12 @@ struct clock_info { int last_child; int expanded; int level; + char *prefix; struct clock_info *parent; struct clock_info **children; } *clocks_info;
-static struct tree *clock_tree; +static struct tree *clock_tree = NULL;
static int locate_debugfs(char *clk_path) { @@ -123,7 +124,8 @@ out_free: return ret; }
-static int file_read_from_format(char *file, int *value, const char *format) +static int file_read_from_format(const char *file, int *value, + const char *format) { FILE *f; int ret; @@ -137,12 +139,12 @@ static int file_read_from_format(char *file, int *value, const char *format) return !ret ? -1 : 0; }
-static inline int file_read_int(char *file, int *value) +static inline int file_read_int(const char *file, int *value) { return file_read_from_format(file, value, "%d"); }
-static inline int file_read_hex(char *file, int *value) +static inline int file_read_hex(const char *file, int *value) { return file_read_from_format(file, value, "%x"); } @@ -511,6 +513,24 @@ static struct clock_info *clock_alloc(const char *name) return ci; }
+static int fill_clock_cb(struct tree *t, void *data) +{ + struct clock_info *clkinfo; + + clkinfo = clock_alloc(t->name); + if (!clkinfo) + return -1; + + t->private = clkinfo; + clkinfo->level = t->depth; + + file_read_value(t->path, "flags", "%x", &clkinfo->flags); + file_read_value(t->path, "rate", "%d", &clkinfo->rate); + file_read_value(t->path, "usecount", "%d", &clkinfo->usecount); + + return 0; +} + int read_clock_info(char *clkpath) { DIR *dir; @@ -520,6 +540,9 @@ int read_clock_info(char *clkpath) struct clock_info *cur; int ret = -1;
+ if (tree_for_each(clock_tree, fill_clock_cb, NULL)) + return -1; + dir = opendir(clkpath); if (!dir) return -1; @@ -564,6 +587,65 @@ void read_and_dump_clock_info_one(char *clk, bool dump) printf("\n\n"); }
+static inline const char *clock_rate(int *rate) +{ + int r; + + /* GHZ */ + r = *rate >> 30; + if (r) { + *rate = r; + return "GHZ"; + } + + /* MHZ */ + r = *rate >> 20; + if (r) { + *rate = r; + return "MHZ"; + } + + /* KHZ */ + r = *rate >> 10; + if (r) { + *rate = r; + return "KHZ"; + } + + return ""; +} + +static int dump_clock_cb(struct tree *t, void *data) +{ + struct clock_info *clk = t->private; + struct clock_info *pclk; + const char *unit; + int ret = 0; + int rate = clk->rate; + + if (!t->parent) { + printf("/\n"); + clk->prefix = ""; + return 0; + } + + pclk = t->parent->private; + + if (!clk->prefix) + ret = asprintf(&clk->prefix, "%s%s%s", pclk->prefix, + t->depth > 1 ? " ": "", t->next ? "|" : " "); + if (ret < 0) + return -1; + + unit = clock_rate(&rate); + + printf("%s%s-- %s (flags:0x%x, usecount:%d, rate: %d %s)\n", + clk->prefix, !t->next ? "`" : "", t->name, clk->flags, + clk->usecount, rate, unit); + + return 0; +} + void dump_clock_info(struct clock_info *clk, int level, int bmp) { int i, j;
It is replaced by the tree code.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 56 +++----------------------------------------------------- 1 files changed, 3 insertions(+), 53 deletions(-)
diff --git a/clocks.c b/clocks.c index 5bb04a4..5f494cd 100644 --- a/clocks.c +++ b/clocks.c @@ -646,59 +646,9 @@ static int dump_clock_cb(struct tree *t, void *data) return 0; }
-void dump_clock_info(struct clock_info *clk, int level, int bmp) +int dump_clock_info(void) { - int i, j; - - if (!clk) - return; - - for (i = 1, j = 0; i < level; i++, j = (i - 1)) { - if (i == (level - 1)) { - if (clk->last_child) - printf("`-- "); - else - printf("|-- "); - } else { - if ((1<<j) & bmp) - printf("| "); - else - printf(" "); - } - } - - if (clk == clocks_info) - printf("%s\n", clk->name); - else { - char *unit = "Hz"; - double drate = (double)clk->rate; - - if (drate > 1000 && drate < 1000000) { - unit = "KHz"; - drate /= 1000; - } - if (drate > 1000000) { - unit = "MHz"; - drate /= 1000000; - } - printf("%s (flags:0x%x,usecount:%d,rate:%5.2f %s)\n", - clk->name, clk->flags, clk->usecount, drate, unit); - } - if (clk->children) { - int tbmp = bmp; - int xbmp = -1; - - if (clk->last_child) { - xbmp ^= 1 << (level - 2); - - xbmp = tbmp & xbmp; - } else - xbmp = bmp; - for (i = 0; i < clk->num_children; i++) { - tbmp = xbmp | (1 << level); - dump_clock_info(clk->children[i], level + 1, tbmp); - } - } + return tree_for_each(clock_tree, dump_clock_cb, NULL); }
void read_and_dump_clock_info(int verbose) @@ -707,6 +657,6 @@ void read_and_dump_clock_info(int verbose) printf("\nClock Tree :\n"); printf("**********\n"); read_clock_info(clk_dir_path); - dump_clock_info(clocks_info, 1, 1); + dump_clock_info(); printf("\n\n"); }
That will be useful to search for a specific node name.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- tree.c | 17 +++++++++++++++++ tree.h | 2 ++ 2 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/tree.c b/tree.c index e681f4f..7466e31 100644 --- a/tree.c +++ b/tree.c @@ -223,3 +223,20 @@ int tree_for_each(struct tree *tree, tree_cb_t cb, void *data)
return tree_for_each(tree->next, cb, data); } + +struct tree *tree_find(struct tree *tree, const char *name) +{ + struct tree *t; + + if (!tree) + return NULL; + + if (!strcmp(tree->name, name)) + return tree; + + t = tree_find(tree->child, name); + if (t) + return t; + + return tree_find(tree->next, name); +} diff --git a/tree.h b/tree.h index 57c70f8..7be3fc4 100644 --- a/tree.h +++ b/tree.h @@ -42,4 +42,6 @@ typedef int (*tree_filter_t)(const char *name);
extern struct tree *tree_load(const char *path, tree_filter_t filter);
+extern struct tree *tree_find(struct tree *tree, const char *name); + extern int tree_for_each(struct tree *tree, tree_cb_t cb, void *data);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 192 +++++++++++++++++++------------------------------------------- tree.c | 11 ++++ tree.h | 2 + 3 files changed, 71 insertions(+), 134 deletions(-)
diff --git a/clocks.c b/clocks.c index 5f494cd..d70d480 100644 --- a/clocks.c +++ b/clocks.c @@ -149,93 +149,81 @@ static inline int file_read_hex(const char *file, int *value) return file_read_from_format(file, value, "%x"); }
-static void dump_parent(struct clock_info *clk, int line, bool dump) +static inline const char *clock_rate(int *rate) { - char *unit = "Hz"; - double drate; - static char spaces[64]; - char str[256]; - static int maxline; + int r;
- if (maxline < line) - maxline = line; + /* GHZ */ + r = *rate >> 30; + if (r) { + *rate = r; + return "GHZ"; + }
- if (clk && clk->parent) - dump_parent(clk->parent, ++line, dump); + /* MHZ */ + r = *rate >> 20; + if (r) { + *rate = r; + return "MHZ"; + }
- drate = (double)clk->rate; - if (drate > 1000 && drate < 1000000) { - unit = "KHz"; - drate /= 1000; - } - if (drate > 1000000) { - unit = "MHz"; - drate /= 1000000; - } - if (clk == clocks_info) { - line++; - strcpy(spaces, ""); - sprintf(str, "%s%s (flags:0x%x,usecount:%d,rate:%5.2f %s)\n", - spaces, clk->name, clk->flags, clk->usecount, drate, - unit); - } else { - if (!(clk->parent == clocks_info)) - strcat(spaces, " "); - sprintf(str, "%s`- %s (flags:0x%x,usecount:%d,rate:%5.2f %s)\n", - spaces, clk->name, clk->flags, clk->usecount, drate, - unit); - } - if (dump) - //printf("line=%d:m%d:l%d %s", maxline - line + 2, maxline, line, str); - printf("%s", str); - else - print_one_clock(maxline - line + 2, str, 1, 0); + /* KHZ */ + r = *rate >> 10; + if (r) { + *rate = r; + return "KHZ"; + } + + return ""; }
-static struct clock_info *find_clock(struct clock_info *clk, char *clkarg) +static int dump_clock_cb(struct tree *t, void *data) { - int i; - struct clock_info *ret = clk; - - if (!strcmp(clk->name, clkarg)) - return ret; + struct clock_info *clk = t->private; + struct clock_info *pclk; + const char *unit; + int ret = 0; + int rate = clk->rate;
- if (clk->children) { - for (i = 0; i < clk->num_children; i++) { - if (!strcmp(clk->children[i]->name, clkarg)) - return clk->children[i]; - } - for (i = 0; i < clk->num_children; i++) { - ret = find_clock(clk->children[i], clkarg); - if (ret) - return ret; - } + if (!t->parent) { + printf("/\n"); + clk->prefix = ""; + return 0; }
- return NULL; + pclk = t->parent->private; + + if (!clk->prefix) + ret = asprintf(&clk->prefix, "%s%s%s", pclk->prefix, + t->depth > 1 ? " ": "", t->next ? "|" : " "); + if (ret < 0) + return -1; + + unit = clock_rate(&rate); + + printf("%s%s-- %s (flags:0x%x, usecount:%d, rate: %d %s)\n", + clk->prefix, !t->next ? "`" : "", t->name, clk->flags, + clk->usecount, rate, unit); + + return 0; }
-static void dump_all_parents(char *clkarg, bool dump) +int dump_clock_info(void) { - struct clock_info *clk; - char spaces[1024]; - - strcpy(spaces, ""); + return tree_for_each(clock_tree, dump_clock_cb, NULL); +}
- clk = find_clock(clocks_info, clkarg); +static int dump_all_parents(char *clkarg, bool dump) +{ + struct tree *tree;
- if (!clk) + tree = tree_find(clock_tree, clkarg); + if (!tree) { printf("Clock NOT found!\n"); - else { - /* while(clk && clk != clocks_info) { */ - /* printf("%s\n", clk->name); */ - /* strcat(spaces, " "); */ - /* clk = clk->parent; */ - /* printf("%s <-- ", spaces); */ - /* } */ - /* printf(" /\n"); */ - dump_parent(clk, 1, dump); + return -1; } + + return tree_for_each_parent(tree, dump_clock_cb, NULL); }
void find_parents_for_clock(char *clkname, int complete) @@ -587,70 +575,6 @@ void read_and_dump_clock_info_one(char *clk, bool dump) printf("\n\n"); }
-static inline const char *clock_rate(int *rate) -{ - int r; - - /* GHZ */ - r = *rate >> 30; - if (r) { - *rate = r; - return "GHZ"; - } - - /* MHZ */ - r = *rate >> 20; - if (r) { - *rate = r; - return "MHZ"; - } - - /* KHZ */ - r = *rate >> 10; - if (r) { - *rate = r; - return "KHZ"; - } - - return ""; -} - -static int dump_clock_cb(struct tree *t, void *data) -{ - struct clock_info *clk = t->private; - struct clock_info *pclk; - const char *unit; - int ret = 0; - int rate = clk->rate; - - if (!t->parent) { - printf("/\n"); - clk->prefix = ""; - return 0; - } - - pclk = t->parent->private; - - if (!clk->prefix) - ret = asprintf(&clk->prefix, "%s%s%s", pclk->prefix, - t->depth > 1 ? " ": "", t->next ? "|" : " "); - if (ret < 0) - return -1; - - unit = clock_rate(&rate); - - printf("%s%s-- %s (flags:0x%x, usecount:%d, rate: %d %s)\n", - clk->prefix, !t->next ? "`" : "", t->name, clk->flags, - clk->usecount, rate, unit); - - return 0; -} - -int dump_clock_info(void) -{ - return tree_for_each(clock_tree, dump_clock_cb, NULL); -} - void read_and_dump_clock_info(int verbose) { (void)verbose; diff --git a/tree.c b/tree.c index 7466e31..0a9c119 100644 --- a/tree.c +++ b/tree.c @@ -224,6 +224,17 @@ int tree_for_each(struct tree *tree, tree_cb_t cb, void *data) return tree_for_each(tree->next, cb, data); }
+int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data) +{ + if (!tree) + return 0; + + if (tree_for_each_parent(tree->parent, cb, data)) + return -1; + + return cb(tree, data); +} + struct tree *tree_find(struct tree *tree, const char *name) { struct tree *t; diff --git a/tree.h b/tree.h index 7be3fc4..176dd23 100644 --- a/tree.h +++ b/tree.h @@ -45,3 +45,5 @@ extern struct tree *tree_load(const char *path, tree_filter_t filter); extern struct tree *tree_find(struct tree *tree, const char *name);
extern int tree_for_each(struct tree *tree, tree_cb_t cb, void *data); + +extern int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clocks.c b/clocks.c index d70d480..8e3509c 100644 --- a/clocks.c +++ b/clocks.c @@ -213,7 +213,7 @@ int dump_clock_info(void) return tree_for_each(clock_tree, dump_clock_cb, NULL); }
-static int dump_all_parents(char *clkarg, bool dump) +static int dump_all_parents(char *clkarg) { struct tree *tree;
@@ -241,7 +241,7 @@ void find_parents_for_clock(char *clkname, int complete) } sprintf(name, "Parents for "%s" Clock : \n", clkname); print_one_clock(0, name, 1, 1); - dump_all_parents(clkname, false); + dump_all_parents(clkname); }
static void destroy_clocks_info_recur(struct clock_info *clock) @@ -571,7 +571,7 @@ void read_and_dump_clock_info_one(char *clk, bool dump) { printf("\nParents for "%s" Clock :\n\n", clk); read_clock_info(clk_dir_path); - dump_all_parents(clk, dump); + dump_all_parents(clk); printf("\n\n"); }
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 2 +- powerdebug.c | 3 +-- powerdebug.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/clocks.c b/clocks.c index 8e3509c..5bcef51 100644 --- a/clocks.c +++ b/clocks.c @@ -567,7 +567,7 @@ out: return ret; }
-void read_and_dump_clock_info_one(char *clk, bool dump) +void read_and_dump_clock_info_one(char *clk) { printf("\nParents for "%s" Clock :\n\n", clk); read_clock_info(clk_dir_path); diff --git a/powerdebug.c b/powerdebug.c index af8d28c..f71a9df 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -313,8 +313,7 @@ static int powerdebug_dump(struct powerdebug_options *options, if (options->clocks) {
if (options->clkname) - read_and_dump_clock_info_one(options->clkname, - options->dump); + read_and_dump_clock_info_one(options->clkname); else read_and_dump_clock_info(options->verbose); } diff --git a/powerdebug.h b/powerdebug.h index 0d8e8d1..8e0c658 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -29,7 +29,7 @@ enum {CLOCK, REGULATOR, SENSOR}; enum {CLOCK_SELECTED = 1, REFRESH_WINDOW};
extern void read_and_dump_clock_info(int verbose); -extern void read_and_dump_clock_info_one(char *clk, bool dump); +extern void read_and_dump_clock_info_one(char *clk); extern int read_clock_info(char *clkpath); extern void find_parents_for_clock(char *clkname, int complete); extern int read_and_print_clock_info(int verbose, int hrow, int selected);
the verbose option is unused.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 24 +++++++++++------------- powerdebug.c | 9 ++------- powerdebug.h | 3 +-- 3 files changed, 14 insertions(+), 22 deletions(-)
diff --git a/clocks.c b/clocks.c index 5bcef51..9d8108c 100644 --- a/clocks.c +++ b/clocks.c @@ -567,20 +567,18 @@ out: return ret; }
-void read_and_dump_clock_info_one(char *clk) +void read_and_dump_clock_info(char *clk) { - printf("\nParents for "%s" Clock :\n\n", clk); read_clock_info(clk_dir_path); - dump_all_parents(clk); - printf("\n\n"); -}
-void read_and_dump_clock_info(int verbose) -{ - (void)verbose; - printf("\nClock Tree :\n"); - printf("**********\n"); - read_clock_info(clk_dir_path); - dump_clock_info(); - printf("\n\n"); + if (clk) { + printf("\nParents for "%s" Clock :\n\n", clk); + dump_all_parents(clk); + printf("\n\n"); + } else { + printf("\nClock Tree :\n"); + printf("**********\n"); + dump_clock_info(); + printf("\n\n"); + } } diff --git a/powerdebug.c b/powerdebug.c index f71a9df..71c37f2 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -310,13 +310,8 @@ static int powerdebug_dump(struct powerdebug_options *options, regulator_print_info(reg_info, nr_reg, options->verbose); }
- if (options->clocks) { - - if (options->clkname) - read_and_dump_clock_info_one(options->clkname); - else - read_and_dump_clock_info(options->verbose); - } + if (options->clocks) + read_and_dump_clock_info(options->clkname);
if (options->sensors) read_and_print_sensor_info(options->verbose); diff --git a/powerdebug.h b/powerdebug.h index 8e0c658..d2c0954 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -28,8 +28,7 @@ enum {CLOCK, REGULATOR, SENSOR}; enum {CLOCK_SELECTED = 1, REFRESH_WINDOW};
-extern void read_and_dump_clock_info(int verbose); -extern void read_and_dump_clock_info_one(char *clk); +extern void read_and_dump_clock_info(char *clk); extern int read_clock_info(char *clkpath); extern void find_parents_for_clock(char *clkname, int complete); extern int read_and_print_clock_info(int verbose, int hrow, int selected);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 8 +++----- powerdebug.c | 1 - powerdebug.h | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/clocks.c b/clocks.c index 9d8108c..e843b9e 100644 --- a/clocks.c +++ b/clocks.c @@ -283,7 +283,7 @@ static void destroy_clocks_info(void) }
-int read_and_print_clock_info(int verbose, int hrow, int selected) +int read_and_print_clock_info(int hrow, int selected) { print_one_clock(0, "Reading Clock Tree ...", 1, 1);
@@ -302,7 +302,7 @@ int read_and_print_clock_info(int verbose, int hrow, int selected) else selected = 0;
- print_clock_info(verbose, hrow, selected); + print_clock_info(hrow, selected); hrow = (hrow < old_clock_line_no) ? hrow : old_clock_line_no - 1;
return hrow; @@ -380,12 +380,10 @@ static void add_clock_details_recur(struct clock_info *clock, strcpy(clock_lines[clock_line_no], ""); }
-void print_clock_info(int verbose, int hrow, int selected) +void print_clock_info(int hrow, int selected) { int i, count = 0, delta;
- (void)verbose; - print_clock_header();
for (i = 0; i < clocks_info->num_children; i++) diff --git a/powerdebug.c b/powerdebug.c index 71c37f2..7d89a7b 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -271,7 +271,6 @@ int mainloop(struct powerdebug_options *options, if (refreshwin) command = REFRESH_WINDOW; hrow = read_and_print_clock_info( - options->verbose, highlighted_row, command); highlighted_row = hrow; diff --git a/powerdebug.h b/powerdebug.h index d2c0954..535f194 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -31,8 +31,8 @@ enum {CLOCK_SELECTED = 1, REFRESH_WINDOW}; extern void read_and_dump_clock_info(char *clk); extern int read_clock_info(char *clkpath); extern void find_parents_for_clock(char *clkname, int complete); -extern int read_and_print_clock_info(int verbose, int hrow, int selected); -extern void print_clock_info(int verbose, int hrow, int selected); +extern int read_and_print_clock_info(int hrow, int selected); +extern void print_clock_info(int hrow, int selected); extern void print_string_val(char *name, char *val); extern void print_clock_header(void); extern void print_one_clock(int line, char *str, int bold, int highlight);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- tree.c | 14 ++++++++++++++ tree.h | 2 ++ 2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/tree.c b/tree.c index 0a9c119..516e832 100644 --- a/tree.c +++ b/tree.c @@ -224,6 +224,20 @@ int tree_for_each(struct tree *tree, tree_cb_t cb, void *data) return tree_for_each(tree->next, cb, data); }
+int tree_for_each_reverse(struct tree *tree, tree_cb_t cb, void *data) +{ + if (!tree) + return 0; + + if (cb(tree, data)) + return -1; + + if (tree_for_each_reverse(tree->prev, cb, data)) + return -1; + + return tree_for_each_reverse(tree->parent, cb, data); +} + int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data) { if (!tree) diff --git a/tree.h b/tree.h index 176dd23..2af4a5a 100644 --- a/tree.h +++ b/tree.h @@ -46,4 +46,6 @@ extern struct tree *tree_find(struct tree *tree, const char *name);
extern int tree_for_each(struct tree *tree, tree_cb_t cb, void *data);
+extern int tree_for_each_reverse(struct tree *tree, tree_cb_t cb, void *data); + extern int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data);
... needed at least for gdb ...
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- powerdebug.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/powerdebug.c b/powerdebug.c index 7d89a7b..8e7e78e 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -288,10 +288,17 @@ int mainloop(struct powerdebug_options *options, tval.tv_sec = options->ticktime; tval.tv_usec = (options->ticktime - tval.tv_sec) * 1000000;
+ again: key = select(1, &readfds, NULL, NULL, &tval); if (!key) continue;
+ if (key < 0) { + if (errno == EINTR) + goto again; + break; + } + if (keystroke_callback(&enter_hit, &findparent_ncurses, clkname_str, &refreshwin, options)) break;
This patch provides a function returning all the node of the tree matching the substring passed a parameter.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- tree.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ tree.h | 2 ++ 2 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/tree.c b/tree.c index 516e832..8f546a9 100644 --- a/tree.c +++ b/tree.c @@ -265,3 +265,51 @@ struct tree *tree_find(struct tree *tree, const char *name)
return tree_find(tree->next, name); } + +struct struct_find { + int nr; + const char *name; + struct tree ***ptree; +}; + +static int tree_finds_cb(struct tree *tree, void *data) +{ + struct struct_find *sf = data; + + if (strncmp(sf->name, tree->name, strlen(sf->name))) + return 0; + + if (sf->ptree) + (*(sf->ptree))[sf->nr] = tree; + + sf->nr++; + + return 0; +} + +int tree_finds(struct tree *tree, const char *name, struct tree ***ptr) +{ + struct struct_find sf = { .nr = 0, .ptree = NULL, .name = name }; + int nmatch; + + /* first pass : count # of matching nodes */ + tree_for_each(tree, tree_finds_cb, &sf); + + /* no match */ + if (!sf.nr) + return 0; + + *ptr = malloc(sizeof(struct tree *) * sf.nr); + if (!*ptr) + return -1; + + /* store the result as it will be overwritten by the next call */ + nmatch = sf.nr; + sf.nr = 0; + sf.ptree = ptr; + + /* second pass : fill with the matching nodes */ + tree_for_each(tree, tree_finds_cb, &sf); + + return nmatch; +} diff --git a/tree.h b/tree.h index 2af4a5a..88d4a19 100644 --- a/tree.h +++ b/tree.h @@ -49,3 +49,5 @@ extern int tree_for_each(struct tree *tree, tree_cb_t cb, void *data); extern int tree_for_each_reverse(struct tree *tree, tree_cb_t cb, void *data);
extern int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data); + +extern int tree_finds(struct tree *tree, const char *name, struct tree ***ptr);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- tree.c | 3 +++ tree.h | 1 + 2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/tree.c b/tree.c index 8f546a9..dd53ff2 100644 --- a/tree.c +++ b/tree.c @@ -57,6 +57,7 @@ static inline struct tree *tree_alloc(const char *path, int depth) t->next = NULL; t->prev = NULL; t->private = NULL; + t->nrchild = 0;
return t; } @@ -161,6 +162,8 @@ static int tree_scan(struct tree *tree, tree_filter_t filter)
tree_add_child(tree, child);
+ tree->nrchild++; + ret = tree_scan(child, filter); }
diff --git a/tree.h b/tree.h index 88d4a19..c7f3ca9 100644 --- a/tree.h +++ b/tree.h @@ -33,6 +33,7 @@ struct tree { char *path; char *name; void *private; + int nrchild; unsigned char depth; };
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- tree.c | 35 +++++++++++++++++++++++++++++++++++ 1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/tree.c b/tree.c index dd53ff2..f95610a 100644 --- a/tree.c +++ b/tree.c @@ -227,6 +227,15 @@ int tree_for_each(struct tree *tree, tree_cb_t cb, void *data) return tree_for_each(tree->next, cb, data); }
+/* + * This function will go over the tree passed as parameter at the reverse + * order and will call the callback passed as parameter for each. + * @tree : the lower node where we begin to browse the tree at the reverse + * order + * cb : a callback for each node the function will go over + * data : some private data to be passed across the callbacks + * Returns 0 on success, < 0 otherwise + */ int tree_for_each_reverse(struct tree *tree, tree_cb_t cb, void *data) { if (!tree) @@ -241,6 +250,15 @@ int tree_for_each_reverse(struct tree *tree, tree_cb_t cb, void *data) return tree_for_each_reverse(tree->parent, cb, data); }
+ +/* + * The function will go over all the parent of the specified node passed + * as parameter. + * @tree : the child node from where we back path to the parent + * cb : a callback for each node the function will go over + * data : some private data to be passed across the callbacks + * Returns 0 on success, < 0 otherwise + */ int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data) { if (!tree) @@ -252,6 +270,13 @@ int tree_for_each_parent(struct tree *tree, tree_cb_t cb, void *data) return cb(tree, data); }
+/* + * The function will return the first node which match with the name as + * parameter. + * @tree : the tree where we begin to find + * @name : the name of the node the function must look for. + * Returns a pointer to the tree structure if found, NULL otherwise. + */ struct tree *tree_find(struct tree *tree, const char *name) { struct tree *t; @@ -290,6 +315,16 @@ static int tree_finds_cb(struct tree *tree, void *data) return 0; }
+/* + * This function will search for all the nodes where the name begin + * with the name passed as parameter. *Note* the function allocates + * the array, it is up to the caller to free this array. + * @tree : the topmost node of the tree where we being to search + * @name : the name to find in the tree + * @ptr : a pointer to a pointer of pointer of tree structure :) + * Returns the number of elements found in the tree, < 0 if something + * went wrong. + */ int tree_finds(struct tree *tree, const char *name, struct tree ***ptr) { struct struct_find sf = { .nr = 0, .ptree = NULL, .name = name };
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 422 +++++++++++++++++++--------------------------------------- display.c | 160 +++++++++++++++++++---- powerdebug.c | 66 ++++++---- powerdebug.h | 19 ++- 4 files changed, 325 insertions(+), 342 deletions(-)
diff --git a/clocks.c b/clocks.c index e843b9e..de5476a 100644 --- a/clocks.c +++ b/clocks.c @@ -11,6 +11,10 @@ * Contributors: * Amit Arora amit.arora@linaro.org (IBM Corporation) * - initial API and implementation + * + * Daniel Lezcano daniel.lezcano@linaro.org (IBM Corporation) + * - Rewrote code and API + * *******************************************************************************/
#ifndef _GNU_SOURCE @@ -25,26 +29,12 @@ #include "clocks.h" #include "tree.h"
-#define MAX_LINES 120 - -static char clk_dir_path[PATH_MAX]; -static int bold[MAX_LINES]; -static char clock_lines[MAX_LINES][128]; -static int clock_line_no; -static int old_clock_line_no; - struct clock_info { - char name[NAME_MAX]; int flags; int rate; int usecount; - int num_children; - int last_child; - int expanded; - int level; + bool expanded; char *prefix; - struct clock_info *parent; - struct clock_info **children; } *clocks_info;
static struct tree *clock_tree = NULL; @@ -74,18 +64,15 @@ static int locate_debugfs(char *clk_path) return ret; }
-int clock_init(void) +static struct clock_info *clock_alloc(void) { - if (locate_debugfs(clk_dir_path)) - return -1; - - sprintf(clk_dir_path, "%s/clock", clk_dir_path); + struct clock_info *ci;
- clock_tree = tree_load(clk_dir_path, NULL); - if (!clock_tree) - return -1; + ci = malloc(sizeof(*ci)); + if (ci) + memset(ci, 0, sizeof(*ci));
- return access(clk_dir_path, F_OK); + return ci; }
/* @@ -236,347 +223,206 @@ void find_parents_for_clock(char *clkname, int complete)
strcat(name, clkname); sprintf(str, "Enter Clock Name : %s\n", name); - print_one_clock(2, str, 1, 0); + display_reset_cursor(); + display_print_line(0, str, 1, NULL); + display_refresh_pad(); return; } sprintf(name, "Parents for "%s" Clock : \n", clkname); - print_one_clock(0, name, 1, 1); + display_reset_cursor(); + display_print_line(0, name, 1, NULL); + display_refresh_pad(); dump_all_parents(clkname); }
-static void destroy_clocks_info_recur(struct clock_info *clock) +static inline int read_clock_cb(struct tree *t, void *data) { - int i; - - if (clock && clock->num_children) { - for (i = (clock->num_children - 1); i >= 0; i--) { - fflush(stdin); - destroy_clocks_info_recur(clock->children[i]); - if (!i) { - free(clock->children); - clock->children = NULL; - clock->num_children = 0; - } - } - } -} - -static void destroy_clocks_info(void) -{ - int i; + struct clock_info *clk = t->private;
- if (!clocks_info) - return; + file_read_value(t->path, "flags", "%x", &clk->flags); + file_read_value(t->path, "rate", "%d", &clk->rate); + file_read_value(t->path, "usecount", "%d", &clk->usecount);
- if (clocks_info->num_children) { - for (i = (clocks_info->num_children - 1); i >= 0 ; i--) { - destroy_clocks_info_recur(clocks_info->children[i]); - if (!i) { - free(clocks_info->children); - clocks_info->children = NULL; - } - } - } - clocks_info->num_children = 0; - free(clocks_info); - clocks_info = NULL; + return 0; }
+static int read_clock_info(void) +{ + return tree_for_each(clock_tree, read_clock_cb, NULL); +}
-int read_and_print_clock_info(int hrow, int selected) +static int fill_clock_cb(struct tree *t, void *data) { - print_one_clock(0, "Reading Clock Tree ...", 1, 1); + struct clock_info *clk;
- if (!old_clock_line_no || selected == REFRESH_WINDOW) { - destroy_clocks_info(); - read_clock_info(clk_dir_path); - } + clk = clock_alloc(); + if (!clk) + return -1; + t->private = clk;
- if (!clocks_info || !clocks_info->num_children) { - fprintf(stderr, "powerdebug: No clocks found. Exiting..\n"); - exit(1); + /* we skip the root node but we set it expanded for its children */ + if (!t->parent) { + clk->expanded = true; + return 0; }
- if (selected == CLOCK_SELECTED) - selected = 1; - else - selected = 0; - - print_clock_info(hrow, selected); - hrow = (hrow < old_clock_line_no) ? hrow : old_clock_line_no - 1; - - return hrow; + return read_clock_cb(t, data); }
-static int calc_delta_screen_size(int hrow) +static int fill_clock_tree(void) { - if (hrow >= (maxy - 3)) - return hrow - (maxy - 4); - - return 0; + return tree_for_each(clock_tree, fill_clock_cb, NULL); }
-static void prepare_name_str(char *namestr, struct clock_info *clock) +static int is_collapsed(struct tree *t, void *data) { - int i; + struct clock_info *clk = t->private;
- strcpy(namestr, ""); - if (clock->level > 1) - for (i = 0; i < (clock->level - 1); i++) - strcat(namestr, " "); - strcat(namestr, clock->name); -} + if (!clk->expanded) + return 1;
-static void collapse_all_subclocks(struct clock_info *clock) -{ - int i; - - clock->expanded = 0; - if (clock->num_children) - for (i = 0; i < clock->num_children; i++) - collapse_all_subclocks(clock->children[i]); + return 0; }
-static void add_clock_details_recur(struct clock_info *clock, - int hrow, int selected) +static char *clock_line(struct tree *t) { - int i; - char *unit = " Hz"; - char rate_str[64]; - char name_str[256]; - double drate = (double)clock->rate; - - if (drate > 1000 && drate < 1000000) { - unit = "KHz"; - drate /= 1000; - } - if (drate > 1000000) { - unit = "MHz"; - drate /= 1000000; - } - if (clock->usecount) - bold[clock_line_no] = 1; - else - bold[clock_line_no] = 0; - - sprintf(rate_str, "%.2f %s", drate, unit); - prepare_name_str(name_str, clock); - sprintf(clock_lines[clock_line_no++], "%-55s 0x%-4x %-12s %-12d %-12d", - name_str, clock->flags, rate_str, clock->usecount, - clock->num_children); - - if (selected && (hrow == (clock_line_no - 1))) { - if (clock->expanded) - collapse_all_subclocks(clock); - else - clock->expanded = 1; - selected = 0; - } - - if (clock->expanded && clock->num_children) - for (i = 0; i < clock->num_children; i++) - add_clock_details_recur(clock->children[i], - hrow, selected); - strcpy(clock_lines[clock_line_no], ""); -} + struct clock_info *clk; + int rate; + const char *clkunit; + char *clkrate, *clkname, *clkline = NULL;
-void print_clock_info(int hrow, int selected) -{ - int i, count = 0, delta; + clk = t->private; + rate = clk->rate; + clkunit = clock_rate(&rate);
- print_clock_header(); + if (asprintf(&clkname, "%*s%s", (t->depth - 1) * 2, "", t->name) < 0) + return NULL;
- for (i = 0; i < clocks_info->num_children; i++) - add_clock_details_recur(clocks_info->children[i], - hrow, selected); + if (asprintf(&clkrate, "%d%s", rate, clkunit) < 0) + goto free_clkname;
- delta = calc_delta_screen_size(hrow); + if (asprintf(&clkline, "%-55s 0x%-16x %-12s %-9d %-8d", clkname, + clk->flags, clkrate, clk->usecount, t->nrchild) < 0) + goto free_clkrate;
- while (clock_lines[count + delta] && - strcmp(clock_lines[count + delta], "")) { - if (count < delta) { - count++; - continue; - } - print_one_clock(count - delta, clock_lines[count + delta], - bold[count + delta], (hrow == (count + delta))); - count++; - } +free_clkrate: + free(clkrate); +free_clkname: + free(clkname);
- old_clock_line_no = clock_line_no; - clock_line_no = 0; + return clkline; }
-static void insert_children(struct clock_info **parent, struct clock_info *clk) +static int clock_print_info_cb(struct tree *t, void *data) { - if (!(*parent)->num_children || (*parent)->children == NULL) { - (*parent)->children = (struct clock_info **) - malloc(sizeof(struct clock_info *)*2); - (*parent)->num_children = 0; - } else - (*parent)->children = (struct clock_info **) - realloc((*parent)->children, - sizeof(struct clock_info *) * - ((*parent)->num_children + 2)); - if ((*parent)->num_children > 0) - (*parent)->children[(*parent)->num_children - 1]->last_child - = 0; - clk->last_child = 1; - (*parent)->children[(*parent)->num_children] = clk; - (*parent)->children[(*parent)->num_children + 1] = NULL; - (*parent)->num_children++; -} + struct clock_info *clock = t->private; + int *line = data; + char *buffer;
-static struct clock_info *read_clock_info_recur(char *clkpath, int level, - struct clock_info *parent) -{ - int ret = 0; - DIR *dir; - char filename[PATH_MAX]; - struct dirent *item; - struct clock_info *cur = NULL; - struct stat buf; - - dir = opendir(clkpath); - if (!dir) - return NULL; - - while ((item = readdir(dir))) { - struct clock_info *child; - /* skip hidden dirs except ".." */ - if (item->d_name[0] == '.' ) - continue; - - sprintf(filename, "%s/%s", clkpath, item->d_name); + /* we skip the root node of the tree */ + if (!t->parent) + return 0;
- ret = stat(filename, &buf); + /* show the clock when *all* its parent is expanded */ + if (tree_for_each_parent(t->parent, is_collapsed, NULL)) + return 0;
- if (ret < 0) { - printf("Error doing a stat on %s\n", filename); - exit(1); - } + buffer = clock_line(t); + if (!buffer) + return -1;
- if (S_ISREG(buf.st_mode)) { - if (!strcmp(item->d_name, "flags")) - file_read_hex(filename, &parent->flags); - if (!strcmp(item->d_name, "rate")) - file_read_int(filename, &parent->rate); - if (!strcmp(item->d_name, "usecount")) - file_read_int(filename, &parent->usecount); - continue; - } + display_print_line(*line, buffer, clock->usecount, t);
- if (!S_ISDIR(buf.st_mode)) - continue; + (*line)++;
- cur = (struct clock_info *)malloc(sizeof(struct clock_info)); - memset(cur, 0, sizeof(cur)); - strcpy(cur->name, item->d_name); - cur->children = NULL; - cur->parent = NULL; - cur->num_children = 0; - cur->expanded = 0; - cur->level = level; - child = read_clock_info_recur(filename, level + 1, cur); - insert_children(&parent, cur); - cur->parent = parent; - } - closedir(dir); + free(buffer);
- return cur; + return 0; }
-static struct clock_info *clock_alloc(const char *name) +static int clock_print_info(void) { - struct clock_info *ci; + int ret, line = 0;
- ci = malloc(sizeof(*ci)); - if (ci) { - memset(ci, 0, sizeof(*ci)); - strcpy(ci->name, name); - } + print_clock_header();
- return ci; -} + display_reset_cursor();
-static int fill_clock_cb(struct tree *t, void *data) -{ - struct clock_info *clkinfo; + ret = tree_for_each(clock_tree, clock_print_info_cb, &line);
- clkinfo = clock_alloc(t->name); - if (!clkinfo) - return -1; + display_refresh_pad(); + + return ret; +}
- t->private = clkinfo; - clkinfo->level = t->depth; +int clock_toggle_expanded(void) +{ + struct tree *t = display_get_row_data(); + struct clock_info *clk = t->private;
- file_read_value(t->path, "flags", "%x", &clkinfo->flags); - file_read_value(t->path, "rate", "%d", &clkinfo->rate); - file_read_value(t->path, "usecount", "%d", &clkinfo->usecount); + clk->expanded = !clk->expanded;
return 0; }
-int read_clock_info(char *clkpath) +/* + * Initialize the clock framework + */ +int clock_init(void) { - DIR *dir; - struct dirent *item; - char filename[NAME_MAX]; - struct clock_info *child; - struct clock_info *cur; - int ret = -1; + char clk_dir_path[PATH_MAX];
- if (tree_for_each(clock_tree, fill_clock_cb, NULL)) + if (locate_debugfs(clk_dir_path)) return -1;
- dir = opendir(clkpath); - if (!dir) - return -1; + sprintf(clk_dir_path, "%s/clock", clk_dir_path);
- clocks_info = clock_alloc("/"); - if (!clocks_info) + if (access(clk_dir_path, F_OK)) return -1;
- while ((item = readdir(dir))) { - - /* skip hidden dirs except ".." */ - if (item->d_name[0] == '.') - continue; - - sprintf(filename, "%s/%s", clkpath, item->d_name); - - cur = clock_alloc(item->d_name); - if (!cur) - goto out; - - cur->parent = clocks_info; - cur->num_children = 0; - cur->expanded = 0; - cur->level = 1; - insert_children(&clocks_info, cur); - child = read_clock_info_recur(filename, 2, cur); - } + clock_tree = tree_load(clk_dir_path, NULL); + if (!clock_tree) + return -1;
- ret = 0; + return fill_clock_tree(); +}
-out: - closedir(dir); +/* + * Read the clock information and fill the tree with the information + * found in the files. Then print the result to the text based interface + * Return 0 on success, < 0 otherwise + */ +int read_and_print_clock_info(int hrow, int selected) +{ + if (read_clock_info()) + return -1;
- return ret; + return clock_print_info(); }
-void read_and_dump_clock_info(char *clk) +/* + * Read the clock information and fill the tree with the information + * found in the files. Then dump to stdout a formatted result. + * @clk : a name for a specific clock we want to show + * Return 0 on success, < 0 otherwise + */ +int read_and_dump_clock_info(char *clk) { - read_clock_info(clk_dir_path); + int ret; + + if (read_clock_info()) + return -1;
if (clk) { printf("\nParents for "%s" Clock :\n\n", clk); - dump_all_parents(clk); + ret = dump_all_parents(clk); printf("\n\n"); } else { printf("\nClock Tree :\n"); printf("**********\n"); - dump_clock_info(); + ret = dump_clock_info(); printf("\n\n"); } + + return ret; } diff --git a/display.c b/display.c index dd5543c..98dc955 100644 --- a/display.c +++ b/display.c @@ -32,11 +32,16 @@ enum { PT_COLOR_DEFAULT = 1,
static WINDOW *header_win; static WINDOW *regulator_win; -static WINDOW *clock_win; +static WINDOW *clock_pad; +static WINDOW *clock_labels; static WINDOW *sensor_win; static WINDOW *footer_win;
int maxx, maxy; + +/* Number of lines in the virtual window */ +static const int maxrows = 1024; + static char footer_items[NUM_FOOTER_ITEMS][64];
static char *win_names[TOTAL_FEATURE_WINS] = { @@ -45,6 +50,16 @@ static char *win_names[TOTAL_FEATURE_WINS] = { "Sensors" };
+struct rowdata { + int attr; + void *data; +}; + +static struct rowdata *rowdata; +static int nrdata; +static int scrolling; +static int cursor; + static void display_fini(void) { endwin(); @@ -83,8 +98,12 @@ int display_init(void) if (!regulator_win) return -1;
- clock_win = subwin(stdscr, maxy - 2, maxx, 1, 0); - if (!clock_win) + clock_labels = subwin(stdscr, maxy - 2, maxx, 1, 0); + if (!clock_labels) + return -1; + + clock_pad = newpad(maxrows, maxx); + if (!clock_pad) return -1;
sensor_win = subwin(stdscr, maxy - 2, maxx, 1, 0); @@ -127,10 +146,6 @@ void create_selectedwindow(int selectedwindow) wrefresh(regulator_win); break;
- case CLOCK: - wrefresh(clock_win); - break; - case SENSOR: wrefresh(sensor_win); break; @@ -234,15 +249,15 @@ void show_regulator_info(struct regulator_info *reg_info, int nr_reg, int verbos
void print_clock_header(void) { - werase(clock_win); - wattron(clock_win, A_BOLD); - print(clock_win, 0, 0, "Name"); - print(clock_win, 54, 0, "Flags"); - print(clock_win, 64, 0, "Rate"); - print(clock_win, 72, 0, "Usecount"); - print(clock_win, 84, 0, "Children"); - wattroff(clock_win, A_BOLD); - wrefresh(clock_win); + werase(clock_labels); + wattron(clock_labels, A_BOLD); + print(clock_labels, 0, 0, "Name"); + print(clock_labels, 56, 0, "Flags"); + print(clock_labels, 75, 0, "Rate"); + print(clock_labels, 88, 0, "Usecount"); + print(clock_labels, 98, 0, "Children"); + wattroff(clock_labels, A_BOLD); + wrefresh(clock_labels); }
void print_sensor_header(void) @@ -259,17 +274,110 @@ void print_sensor_header(void) wrefresh(sensor_win); }
-void print_one_clock(int line, char *str, int bold, int highlight) +int display_refresh_pad(void) { - if (bold) - wattron(clock_win, WA_BOLD); - if (highlight) - wattron(clock_win, WA_STANDOUT); + return prefresh(clock_pad, scrolling, 0, 2, 0, maxy - 2, maxx); +} + +static int inline display_clock_un_select(int line, bool highlight, bool bold) +{ + if (mvwchgat(clock_pad, line, 0, -1, + highlight ? WA_STANDOUT : + bold ? WA_BOLD: WA_NORMAL, 0, NULL) < 0) + return -1; + + return display_refresh_pad(); +} + +int display_clock_select(int line) +{ + return display_clock_un_select(line, true, false); +} + +int display_clock_unselect(int line, bool bold) +{ + return display_clock_un_select(line, false, bold); +} + +void *display_get_row_data(void) +{ + return rowdata[cursor].data; +} + +int display_set_row_data(int line, void *data, int attr) +{ + if (line >= nrdata) { + rowdata = realloc(rowdata, sizeof(struct rowdata) * (line + 1)); + if (!rowdata) + return -1; + nrdata = line + 1; + } + + rowdata[line].data = data; + rowdata[line].attr = attr; + + return 0; +} + +int display_reset_cursor(void) +{ + nrdata = 0; + werase(clock_pad); + return wmove(clock_pad, 0, 0); +} + +int display_print_line(int line, char *str, int bold, void *data) +{ + int attr = 0;
- print(clock_win, 0, line + 1, "%s", str); if (bold) - wattroff(clock_win, WA_BOLD); - if (highlight) - wattroff(clock_win, WA_STANDOUT); - wrefresh(clock_win); + attr |= WA_BOLD; + + if (line == cursor) + attr |= WA_STANDOUT; + + if (display_set_row_data(line, data, attr)) + return -1; + + if (attr) + wattron(clock_pad, attr); + + wprintw(clock_pad, "%s\n", str); + + if (attr) + wattroff(clock_pad, attr); + + return 0; +} + +int display_next_line(void) +{ + if (cursor >= nrdata) + return cursor; + + display_clock_unselect(cursor, rowdata[cursor].attr); + if (cursor < nrdata - 1) { + if (cursor >= (maxy - 4 + scrolling)) + scrolling++; + cursor++; + } + display_clock_select(cursor); + + return cursor; +} + +int display_prev_line(void) +{ + if (cursor >= nrdata) + return cursor; + + display_clock_unselect(cursor, rowdata[cursor].attr); + if (cursor > 0) { + if (cursor <= scrolling) + scrolling--; + cursor--; + } + display_clock_select(cursor); + + return cursor; } diff --git a/powerdebug.c b/powerdebug.c index 8e7e78e..5cf9da7 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -155,7 +155,7 @@ int getoptions(int argc, char *argv[], struct powerdebug_options *options) }
int keystroke_callback(bool *enter_hit, bool *findparent_ncurses, - char *clkname_str, bool *refreshwin, + char *clkname_str, bool *refreshwin, bool *cont, struct powerdebug_options *options) { char keychar; @@ -177,12 +177,22 @@ int keystroke_callback(bool *enter_hit, bool *findparent_ncurses, }
if (options->selectedwindow == CLOCK) { - if (keystroke == KEY_DOWN) - highlighted_row++; - if (keystroke == KEY_UP && highlighted_row > 0) - highlighted_row--; + + if (keystroke == KEY_DOWN) { + display_next_line(); + *cont = true; + } + + if (keystroke == KEY_UP) { + display_prev_line(); + *cont = true; + } + +#if 0 + /* TODO : fix with a new panel applicable for all subsystems */ if (keystroke == '/') *findparent_ncurses = true; +#endif
if ((keystroke == '\e' || oldselectedwin != options->selectedwindow) && *findparent_ncurses) { @@ -240,6 +250,7 @@ int mainloop(struct powerdebug_options *options, bool findparent_ncurses = false; bool refreshwin = false; bool enter_hit = false; + bool cont = false; char clkname_str[64];
strcpy(clkname_str, ""); @@ -249,9 +260,11 @@ int mainloop(struct powerdebug_options *options, struct timeval tval; fd_set readfds;
- create_windows(options->selectedwindow); - show_header(options->selectedwindow); - create_selectedwindow(options->selectedwindow); + if (options->selectedwindow != CLOCK || !cont) { + create_windows(options->selectedwindow); + show_header(options->selectedwindow); + create_selectedwindow(options->selectedwindow); + }
if (options->selectedwindow == REGULATOR) { regulator_read_info(reg_info, nr_reg); @@ -263,21 +276,26 @@ int mainloop(struct powerdebug_options *options,
int hrow;
- if (!findparent_ncurses) { - int command = 0; - - if (enter_hit) - command = CLOCK_SELECTED; - if (refreshwin) - command = REFRESH_WINDOW; - hrow = read_and_print_clock_info( - highlighted_row, - command); - highlighted_row = hrow; - enter_hit = false; - } else - find_parents_for_clock(clkname_str, - enter_hit); + if (!cont) { + + if (!findparent_ncurses) { + int command = 0; + + if (enter_hit) { + clock_toggle_expanded(); + command = CLOCK_SELECTED; + } + if (refreshwin) + command = REFRESH_WINDOW; + hrow = read_and_print_clock_info( + highlighted_row, + command); + highlighted_row = hrow; + enter_hit = false; + } else + find_parents_for_clock(clkname_str, + enter_hit); + } else cont = false; }
if (options->selectedwindow == SENSOR) @@ -300,7 +318,7 @@ int mainloop(struct powerdebug_options *options, }
if (keystroke_callback(&enter_hit, &findparent_ncurses, - clkname_str, &refreshwin, options)) + clkname_str, &refreshwin, &cont, options)) break;
} diff --git a/powerdebug.h b/powerdebug.h index 535f194..760bcfb 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -28,14 +28,25 @@ enum {CLOCK, REGULATOR, SENSOR}; enum {CLOCK_SELECTED = 1, REFRESH_WINDOW};
-extern void read_and_dump_clock_info(char *clk); -extern int read_clock_info(char *clkpath); +extern int read_and_dump_clock_info(char *clk); extern void find_parents_for_clock(char *clkname, int complete); extern int read_and_print_clock_info(int hrow, int selected); -extern void print_clock_info(int hrow, int selected); +extern int print_clock_info(int hrow, int selected); extern void print_string_val(char *name, char *val); extern void print_clock_header(void); -extern void print_one_clock(int line, char *str, int bold, int highlight); + +extern int display_print_line(int line, char *str, int bold, void *data); + +extern int display_refresh_pad(void); +extern int display_reset_cursor(void); +extern int display_next_line(void); +extern int display_prev_line(void); + +extern void *display_get_row_data(void); + +extern int clock_toggle_expanded(void); +extern int display_clock_select(int line); +extern int display_clock_unselect(int line, bool bold);
extern void get_sensor_info(char *path, char *name, char *sensor, int verbose); extern int read_and_print_sensor_info(int verbose);
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org --- clocks.c | 2 +- powerdebug.c | 17 +++-------------- powerdebug.h | 2 +- 3 files changed, 5 insertions(+), 16 deletions(-)
diff --git a/clocks.c b/clocks.c index de5476a..603ebe4 100644 --- a/clocks.c +++ b/clocks.c @@ -392,7 +392,7 @@ int clock_init(void) * found in the files. Then print the result to the text based interface * Return 0 on success, < 0 otherwise */ -int read_and_print_clock_info(int hrow, int selected) +int read_and_print_clock_info(void) { if (read_clock_info()) return -1; diff --git a/powerdebug.c b/powerdebug.c index 5cf9da7..1873b1b 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -21,8 +21,6 @@ #include "clocks.h" #include "powerdebug.h"
-static int highlighted_row; - void usage(void) { printf("Usage: powerdebug [OPTIONS]\n"); @@ -274,23 +272,14 @@ int mainloop(struct powerdebug_options *options,
if (options->selectedwindow == CLOCK) {
- int hrow; - if (!cont) {
if (!findparent_ncurses) { - int command = 0;
- if (enter_hit) { + if (enter_hit) clock_toggle_expanded(); - command = CLOCK_SELECTED; - } - if (refreshwin) - command = REFRESH_WINDOW; - hrow = read_and_print_clock_info( - highlighted_row, - command); - highlighted_row = hrow; + + read_and_print_clock_info(); enter_hit = false; } else find_parents_for_clock(clkname_str, diff --git a/powerdebug.h b/powerdebug.h index 760bcfb..502dcaa 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -30,7 +30,7 @@ enum {CLOCK_SELECTED = 1, REFRESH_WINDOW};
extern int read_and_dump_clock_info(char *clk); extern void find_parents_for_clock(char *clkname, int complete); -extern int read_and_print_clock_info(int hrow, int selected); +extern int read_and_print_clock_info(void); extern int print_clock_info(int hrow, int selected); extern void print_string_val(char *name, char *val); extern void print_clock_header(void);
Hi Daniel,
Thanks for this set. These changes look good in general. Please see comments below.
On 11 Jun 08, Daniel Lezcano wrote:
This patchset introduce a tree structure to store information found in the different directories we are looking for the power management.
The code clock has been replaced by a new code based on this tree.
The result is a code modular and generic enough to be used for the other power management blocks and to add more blocks like the gpio and the thermal framework.
The patch 'rewrite the powerdebug clock code' has been folded in a single one because it was too hard to review the patchset itself.
The display code has been reworked to be generic too but it is still focused on the clock display for the moment.
The following bugs were fixed too:
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794725
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794726
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794728
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794731
The drawback is the find clock interface is broken so it is disabled for the moment. It will be enabled again with the next patchset coming next week.
Daniel Lezcano (23): move clock_info structure definition reorganize code to prevent forward declaration provide a clock allocator remove unused variable fix segfault when the default window is not the clock
This patch doesn't apply. I also find that in your personal tree[1], there are the following additional patches before this series. Should these be part of the series as well?
2ef06e969eb9674b55d1b9704587505ed0e8198e compute next and previous window with modulo arithmetic 3b42b5e49b687837d4ffeabdd6fae207202afb1c make the keyscan code human readable df51b2fe4486032edca1e8f64e4ab61c668e8691 fix display when the default display is not the clock 4b6690736b5d6efe367299df67d2e9b1741e78cf nit : fix output hexadecimal format 00af33efcffc0a52a902d0e181343532f350129d Remove pointless compiler flags
[1] git://git.linaro.org/people/dlezcano/powerdebug.git
refresh the windows instead of killing them and recreate tree structure abstraction for directory hierarchies function helper to read the files use the tree code to dump the clocks Remove old clock tree dump code add 'find' function for the tree use 'find' tree function remove unused parameter remove unused parameter 'options->dump' remove unused code and parameter for clock dump function remove unused 'verbose' option add a function to browse at reverse order the tree make the mainloop immune against the signals add a tree function to return a list of elements compute the number of children for a specific node document the tree code rewrite the powerdebug clock code remove unused 'hrow' and 'selected' parameters
Makefile | 2 +- clocks.c | 639 ++++++++++++++++++++++++---------------------------------- clocks.h | 13 -- display.c | 229 +++++++++++++++------- powerdebug.c | 90 +++++---- powerdebug.h | 26 ++- tree.c | 353 ++++++++++++++++++++++++++++++++ tree.h | 54 +++++ 8 files changed, 890 insertions(+), 516 deletions(-) create mode 100644 tree.c create mode 100644 tree.h
On 06/13/2011 03:52 PM, Amit Kucheria wrote:
Hi Daniel,
Thanks for this set. These changes look good in general. Please see comments below.
On 11 Jun 08, Daniel Lezcano wrote:
This patchset introduce a tree structure to store information found in the different directories we are looking for the power management.
The code clock has been replaced by a new code based on this tree.
The result is a code modular and generic enough to be used for the other power management blocks and to add more blocks like the gpio and the thermal framework.
The patch 'rewrite the powerdebug clock code' has been folded in a single one because it was too hard to review the patchset itself.
The display code has been reworked to be generic too but it is still focused on the clock display for the moment.
The following bugs were fixed too:
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794725
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794726
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794728
- https://bugs.launchpad.net/linaro-pm-wg/+bug/794731
The drawback is the find clock interface is broken so it is disabled for the moment. It will be enabled again with the next patchset coming next week.
Daniel Lezcano (23): move clock_info structure definition reorganize code to prevent forward declaration provide a clock allocator remove unused variable fix segfault when the default window is not the clock
This patch doesn't apply. I also find that in your personal tree[1], there are the following additional patches before this series. Should these be part of the series as well?
2ef06e969eb9674b55d1b9704587505ed0e8198e compute next and previous window with modulo arithmetic 3b42b5e49b687837d4ffeabdd6fae207202afb1c make the keyscan code human readable df51b2fe4486032edca1e8f64e4ab61c668e8691 fix display when the default display is not the clock 4b6690736b5d6efe367299df67d2e9b1741e78cf nit : fix output hexadecimal format 00af33efcffc0a52a902d0e181343532f350129d Remove pointless compiler flags
[1] git://git.linaro.org/people/dlezcano/powerdebug.git
Yes, right.
These are the patches I sent previously http://lists.linaro.org/pipermail/linaro-dev/2011-May/004575.html
Thanks -- Daniel