X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Ftop.c;h=d23067942926a30da8e361319c4419c6a94f0dd1;hb=9932a975e2fdd542be9ff2aee9f66b3209af3e36;hp=76236ead7c5366cf7ef31ae905ce7e62169966d3;hpb=0dc60481cfe21bf7aa7f3b2d4496ef37b62f9c6e;p=monky diff --git a/src/top.c b/src/top.c index 76236ea..d230679 100644 --- a/src/top.c +++ b/src/top.c @@ -11,7 +11,7 @@ * * Copyright (c) 2005 Adi Zaimi, Dan Piponi , * Dave Clark - * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al. + * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al. * (see AUTHORS) * All rights reserved. * @@ -131,7 +131,7 @@ struct process *get_process_by_name(const char *name) struct process *p = first_process; while (p) { - if (!strcmp(p->name, name)) + if (p->name && !strcmp(p->name, name)) return p; p = p->next; } @@ -199,8 +199,8 @@ static struct process *new_process(int p) * Anyone hoping to port wmtop should look here first. */ static int process_parse_stat(struct process *process) { - struct information *cur = &info; char line[BUFFER_LEN] = { 0 }, filename[BUFFER_LEN], procname[BUFFER_LEN]; + char state[4]; int ps; unsigned long user_time = 0; unsigned long kernel_time = 0; @@ -236,13 +236,17 @@ static int process_parse_stat(struct process *process) rc = MIN((unsigned)(rparen - lparen - 1), sizeof(procname) - 1); strncpy(procname, lparen + 1, rc); procname[rc] = '\0'; - rc = sscanf(rparen + 1, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lu " - "%lu %*s %*s %*s %d %*s %*s %*s %u %u", &process->user_time, + rc = sscanf(rparen + 1, "%3s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lu " + "%lu %*s %*s %*s %d %*s %*s %*s %u %u", state, &process->user_time, &process->kernel_time, &nice_val, &process->vsize, &process->rss); - if (rc < 5) { + if (rc < 6) { NORM_ERR("scaning data for %s failed, got only %d fields", procname, rc); return 1; } + + if(state[0]=='R') + ++ info.run_procs; + /* remove any "kdeinit: " */ if (procname == strstr(procname, "kdeinit")) { snprintf(filename, sizeof(filename), PROCFS_CMDLINE_TEMPLATE, @@ -280,12 +284,7 @@ static int process_parse_stat(struct process *process) process->name = strndup(procname, text_buffer_size); process->rss *= getpagesize(); - if (!cur->memmax) { - update_total_processes(); - } - process->total_cpu_time = process->user_time + process->kernel_time; - process->totalmem = (float) (((float) process->rss / cur->memmax) / 10); if (process->previous_user_time == ULONG_MAX) { process->previous_user_time = process->user_time; } @@ -430,6 +429,7 @@ static int update_process_table(void) return 1; } + info.run_procs = 0; ++g_time; /* Get list of processes from /proc directory */ @@ -625,9 +625,9 @@ static int compare_cpu(struct process *a, struct process *b) /* mem comparison function for insert_sp_element */ static int compare_mem(struct process *a, struct process *b) { - if (a->totalmem < b->totalmem) { + if (a->rss < b->rss) { return 1; - } else if (a->totalmem > b->totalmem) { + } else if (a->rss > b->rss) { return -1; } else { return 0; @@ -880,16 +880,22 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) #else /* IOSTATS */ NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize"); #endif /* IOSTATS */ + free_and_zero(td->s); + free_and_zero(obj->data.opaque); return 0; } if (n < 1 || n > 10) { NORM_ERR("invalid num arg for top. Must be between 1 and 10."); + free_and_zero(td->s); + free_and_zero(obj->data.opaque); return 0; } else { td->num = n - 1; } } else { NORM_ERR("invalid argument count for top"); + free_and_zero(td->s); + free_and_zero(obj->data.opaque); return 0; } return 1; @@ -935,11 +941,22 @@ static char *format_time(unsigned long timeval, const int width) return strndup("", text_buffer_size); } -void print_top(struct text_object *obj, char *p, int top_name_width) +static unsigned int top_name_width = 15; + +/* return zero on success, non-zero otherwise */ +int set_top_name_width(const char *s) +{ + if (!s) + return 0; + return !(sscanf(s, "%u", &top_name_width) == 1); +} + +void print_top(struct text_object *obj, char *p, int p_max_size) { struct information *cur = &info; struct top_data *td = obj->data.opaque; struct process **needed = 0; + int width; if (!td) return; @@ -954,58 +971,69 @@ void print_top(struct text_object *obj, char *p, int top_name_width) case OBJ_top_time: needed = cur->time; break; +#ifdef IOSTATS case OBJ_top_io: needed = cur->io; break; +#endif /* IOSTATS */ default: return; } + if (needed[td->num]) { char *timeval; switch (td->type) { case TOP_NAME: - snprintf(p, top_name_width + 1, "%-*s", top_name_width, + width = MIN(p_max_size, (int)top_name_width + 1); + snprintf(p, width + 1, "%-*s", width, needed[td->num]->name); break; case TOP_CPU: - snprintf(p, 7, "%6.2f", + width = MIN(p_max_size, 7); + snprintf(p, width, "%6.2f", needed[td->num]->amount); break; case TOP_PID: - snprintf(p, 6, "%5i", + width = MIN(p_max_size, 6); + snprintf(p, width, "%5i", needed[td->num]->pid); break; case TOP_MEM: - snprintf(p, 7, "%6.2f", - needed[td->num]->totalmem); + /* Calculate a percentage of residential mem from total mem available. + * Since rss is bytes and memmax kilobytes, dividing by 10 suffices here. */ + width = MIN(p_max_size, 7); + snprintf(p, width, "%6.2f", + (float) ((float)needed[td->num]->rss / cur->memmax) / 10); break; case TOP_TIME: + width = MIN(p_max_size, 10); timeval = format_time( needed[td->num]->total_cpu_time, 9); - snprintf(p, 10, "%9s", timeval); + snprintf(p, width, "%9s", timeval); free(timeval); break; case TOP_MEM_RES: human_readable(needed[td->num]->rss, - p, 255); + p, p_max_size); break; case TOP_MEM_VSIZE: human_readable(needed[td->num]->vsize, - p, 255); + p, p_max_size); break; #ifdef IOSTATS case TOP_READ_BYTES: human_readable(needed[td->num]->read_bytes / update_interval, - p, 255); + p, p_max_size); break; case TOP_WRITE_BYTES: human_readable(needed[td->num]->write_bytes / update_interval, - p, 255); + p, p_max_size); break; case TOP_IO_PERC: - snprintf(p, 7, "%6.2f", + width = MIN(p_max_size, 7); + snprintf(p, width, "%6.2f", needed[td->num]->io_perc); break; #endif