diff --git a/src/modules/procstats/e_mod_main.c b/src/modules/procstats/e_mod_main.c index 54cbaf3db..9e547d9da 100644 --- a/src/modules/procstats/e_mod_main.c +++ b/src/modules/procstats/e_mod_main.c @@ -1,4 +1,4 @@ -#include +# include #include "process.h" #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) @@ -6,16 +6,24 @@ # include #endif -static int64_t _mem_total; -static Eina_List *_clients = NULL; -static Ecore_Timer *_clients_timer = NULL; +#define POLL_INTERVAL 2.0 -#define POLL_TIME 3.0 +static int64_t _mem_total; -typedef struct _Proc_Stats Proc_Stats; -struct _Proc_Stats +typedef struct { - E_Client *client; + E_Powersave_Sleeper *sleeper; + Ecore_Thread *thread; + Eina_List *clients; + int poll_interval; + E_Module *e_module; +} Proc_Stats_Module; + +static Proc_Stats_Module *_this_module = NULL; + +typedef struct +{ + E_Client *ec; Evas_Object *obj; Evas_Object *frame_obj; Evas_Object *popup; @@ -24,10 +32,16 @@ struct _Proc_Stats uint64_t mem_size; uint64_t cpu_time; uint64_t cpu_time_prev; -}; +} Proc_Stats_Client; -static void _proc_stats_item_display(Proc_Stats *item); -static void _proc_stats_item_remove(Proc_Stats *item); +static void _proc_stats_client_add(E_Client *ec); +static void _proc_stats_client_display_update(Proc_Stats_Client *client); +static void _proc_stats_client_remove(Proc_Stats_Client *client); +static Eina_Bool _proc_stats_client_exists(E_Client *ec); +static void _proc_stats_client_del(Proc_Stats_Client *client); +static Eina_Bool _proc_stats_client_gone(Proc_Stats_Client *client); +static void _proc_stats_client_children_update(Eina_List *children, Proc_Stats_Client *client); +static void _proc_stats_client_update(Eina_List *procs, Proc_Stats_Client *client); static Eina_Bool _memory_total(void) @@ -61,84 +75,85 @@ _memory_total(void) } static Eina_Bool -_proc_stats_item_exists(E_Client *ec) +_proc_stats_client_exists(E_Client *ec) { - Proc_Stats *item; + Proc_Stats_Client *client; Eina_List *l; + Proc_Stats_Module *module = _this_module; - EINA_LIST_FOREACH(_clients, l, item) + EINA_LIST_FOREACH(module->clients, l, client) { - if (item->pid == ec->netwm.pid) return 1; + if (client->pid == ec->netwm.pid) return 1; } return 0; } static void -_proc_stats_item_del(Proc_Stats *item) +_proc_stats_client_del(Proc_Stats_Client *client) { - if (item->popup) evas_object_del(item->popup); - item->popup = NULL; - edje_object_signal_emit(item->frame_obj, "e,state,procstats,off", "e"); - evas_object_del(item->obj); - e_object_delfn_del(E_OBJECT(item->client), item->delfn); + if (client->popup) evas_object_del(client->popup); + client->popup = NULL; + edje_object_signal_emit(client->frame_obj, "e,state,procstats,off", "e"); + evas_object_del(client->obj); + e_object_delfn_del(E_OBJECT(client->ec), client->delfn); - free(item); - item = NULL; + free(client); + client = NULL; } static void _proc_stats_client_del_cb(void *data, void *obj EINA_UNUSED) { - Proc_Stats *item = data; + Proc_Stats_Client *client = data; - _proc_stats_item_remove(item); + _proc_stats_client_remove(client); } static void _proc_stats_client_move_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - Proc_Stats *item; + Proc_Stats_Client *client; Evas_Coord ox, oy, ow, oh; - item = data; + client = data; - if ((!item) || (!item->popup)) return; + if ((!client) || (!client->popup)) return; - evas_object_geometry_get(item->obj, &ox, &oy, &ow, &oh); - evas_object_move(item->popup, ox + (ow / 2), oy); + evas_object_geometry_get(client->obj, &ox, &oy, &ow, &oh); + evas_object_move(client->popup, ox + (ow / 2), oy); - if ((item->client->hidden) || (item->client->iconic)) - evas_object_hide(item->popup); + if ((client->ec->hidden) || (client->ec->iconic)) + evas_object_hide(client->popup); else - evas_object_show(item->popup); + evas_object_show(client->popup); } static void _proc_stats_icon_clicked_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Up *ev; - Proc_Stats *item; + Proc_Stats_Client *client; Evas_Object *o, *tb; Evas_Object *pb; Evas_Coord ox, oy, ow, oh; ev = event_info; - item = data; + client = data; if (ev->button != 1) return; - if (!item) return; + if (!client) return; - if (item->popup) + if (client->popup) { - evas_object_del(item->popup); - item->popup = NULL; + evas_object_del(client->popup); + client->popup = NULL; return; } - evas_object_geometry_get(item->obj, &ox, &oy, &ow, &oh); + evas_object_geometry_get(client->obj, &ox, &oy, &ow, &oh); - item->popup = o = elm_ctxpopup_add(e_comp->elm); + client->popup = o = elm_ctxpopup_add(e_comp->elm); E_FILL(o); E_EXPAND(o); elm_object_style_set(o, "noblock"); evas_object_layer_set(o, E_LAYER_MENU); @@ -162,7 +177,7 @@ _proc_stats_icon_clicked_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj evas_object_data_set(o, "pb_mem", pb); evas_object_show(pb); - _proc_stats_item_display(item); + _proc_stats_client_display_update(client); elm_ctxpopup_direction_priority_set(o, ELM_CTXPOPUP_DIRECTION_UP, ELM_CTXPOPUP_DIRECTION_DOWN, @@ -173,27 +188,28 @@ _proc_stats_icon_clicked_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj } static void -_proc_stats_item_add(E_Client *ec, E_Module *module) +_proc_stats_client_add(E_Client *ec) { Evas_Object *o; - Proc_Stats *item; + Proc_Stats_Client *client; char buf[PATH_MAX]; + Proc_Stats_Module *module = _this_module; if (ec->internal || ec->netwm.pid == -1) return; if (!ec->frame_object) return; - if (_proc_stats_item_exists(ec)) return; + if (_proc_stats_client_exists(ec)) return; if (!edje_object_part_exists(ec->frame_object, "e.procstats.swallow")) return; - item = calloc(1, sizeof(Proc_Stats)); - EINA_SAFETY_ON_NULL_RETURN(item); + client = calloc(1, sizeof(Proc_Stats_Client)); + EINA_SAFETY_ON_NULL_RETURN(client); o = edje_object_add(e_comp->evas); if (!e_theme_edje_object_set(o, "base/theme/modules/procstats", "e/modules/procstats/border")) { evas_object_del(o); - snprintf(buf, sizeof(buf), "%s/e-module-procstats.edj", e_module_dir_get(module)); + snprintf(buf, sizeof(buf), "%s/e-module-procstats.edj", e_module_dir_get(module->e_module)); o = elm_icon_add(e_comp->elm); elm_image_file_set(o, buf, "icon"); } @@ -201,65 +217,66 @@ _proc_stats_item_add(E_Client *ec, E_Module *module) evas_object_size_hint_max_set(o, ELM_SCALE_SIZE(16), ELM_SCALE_SIZE(16)); E_FILL(o); E_EXPAND(o); - item->obj = o; - item->frame_obj = ec->frame_object; - item->pid = ec->netwm.pid; - item->client = ec; + client->obj = o; + client->frame_obj = ec->frame_object; + client->pid = ec->netwm.pid; + client->ec = ec; - edje_object_part_swallow(ec->frame_object, "e.procstats.swallow", item->obj); - evas_object_show(item->obj); + edje_object_part_swallow(ec->frame_object, "e.procstats.swallow", client->obj); + evas_object_show(client->obj); edje_object_signal_emit(ec->frame_object, "e,state,procstats,on", "e"); - item->delfn = e_object_delfn_add(E_OBJECT(ec), _proc_stats_client_del_cb, item); - evas_object_event_callback_add(item->obj, EVAS_CALLBACK_MOVE, _proc_stats_client_move_cb, item); - evas_object_event_callback_add(item->obj, EVAS_CALLBACK_MOUSE_UP, _proc_stats_icon_clicked_cb, item); + client->delfn = e_object_delfn_add(E_OBJECT(ec), _proc_stats_client_del_cb, client); + evas_object_event_callback_add(client->obj, EVAS_CALLBACK_MOVE, _proc_stats_client_move_cb, client); + evas_object_event_callback_add(client->obj, EVAS_CALLBACK_MOUSE_UP, _proc_stats_icon_clicked_cb, client); - _clients = eina_list_append(_clients, item); + module->clients = eina_list_append(module->clients, client); } static void -_proc_stats_item_remove(Proc_Stats *item) +_proc_stats_client_remove(Proc_Stats_Client *client) { Eina_List *l, *l_next; - Proc_Stats *it; + Proc_Stats_Client *it; + Proc_Stats_Module *module = _this_module; - EINA_LIST_FOREACH_SAFE(_clients, l, l_next, it) + EINA_LIST_FOREACH_SAFE(module->clients, l, l_next, it) { - if (it == item) + if (it == client) { - _proc_stats_item_del(item); - _clients = eina_list_remove_list(_clients, l); + _proc_stats_client_del(client); + module->clients = eina_list_remove_list(module->clients, l); return; } } } static Eina_Bool -_proc_stats_item_gone(Proc_Stats *item) +_proc_stats_client_gone(Proc_Stats_Client *client) { Eina_List *l; E_Client *ec; EINA_LIST_FOREACH(e_comp->clients, l, ec) { - if (item->client == ec) return 0; + if (client->ec == ec) return 0; } return 1; } static void -_proc_stats_item_children_update(Eina_List *children, Proc_Stats *item) +_proc_stats_client_children_update(Eina_List *children, Proc_Stats_Client *client) { Eina_List *l; Proc_Info *child; EINA_LIST_FOREACH(children, l, child) { - item->mem_size += child->mem_size; - item->cpu_time += child->cpu_time; + client->mem_size += child->mem_size; + client->cpu_time += child->cpu_time; if (child->children) - _proc_stats_item_children_update(child->children, item); + _proc_stats_client_children_update(child->children, client); } } @@ -297,7 +314,7 @@ _size_format(unsigned long long bytes) } static void -_proc_stats_item_display(Proc_Stats *item) +_proc_stats_client_display_update(Proc_Stats_Client *client) { Edje_Message_Int_Set *msg; Evas_Object *pb; @@ -305,28 +322,28 @@ _proc_stats_item_display(Proc_Stats *item) char *s; double val = 0.0; - if (item->cpu_time_prev > item->cpu_time) + if (client->cpu_time_prev > client->cpu_time) return; - if (!item->cpu_time_prev) item->cpu_time_prev = item->cpu_time; + if (!client->cpu_time_prev) client->cpu_time_prev = client->cpu_time; msg = malloc(sizeof(Edje_Message_Int_Set) + (sizeof(int) * 4)); EINA_SAFETY_ON_NULL_RETURN(msg); msg->count = 5; msg->val[0] = eina_cpu_count(); - msg->val[1] = (item->cpu_time - item->cpu_time_prev) / POLL_TIME; + msg->val[1] = (client->cpu_time - client->cpu_time_prev) / POLL_INTERVAL; msg->val[2] = (int) (_mem_total / 4096); - msg->val[3] = (int) (item->mem_size / 4096); + msg->val[3] = (int) (client->mem_size / 4096); msg->val[4] = 0; - edje_object_message_send(item->frame_obj, EDJE_MESSAGE_INT_SET, 1973, msg); - edje_object_message_send(item->obj, EDJE_MESSAGE_INT_SET, 1973, msg); + edje_object_message_send(client->frame_obj, EDJE_MESSAGE_INT_SET, 1973, msg); + edje_object_message_send(client->obj, EDJE_MESSAGE_INT_SET, 1973, msg); free(msg); - if (!item->popup) return; + if (!client->popup) return; - pb = evas_object_data_get(item->popup, "pb_cpu"); + pb = evas_object_data_get(client->popup, "pb_cpu"); - val = ((item->cpu_time - item->cpu_time_prev) / POLL_TIME); + val = ((client->cpu_time - client->cpu_time_prev) / POLL_INTERVAL); elm_progressbar_value_set(pb, val / 100.0); buf = eina_strbuf_new(); @@ -335,11 +352,11 @@ _proc_stats_item_display(Proc_Stats *item) elm_object_part_text_set(pb, "elm.text.status", eina_strbuf_string_get(buf)); eina_strbuf_reset(buf); - pb = evas_object_data_get(item->popup, "pb_mem"); - val = item->mem_size / (_mem_total / 100.0); + pb = evas_object_data_get(client->popup, "pb_mem"); + val = client->mem_size / (_mem_total / 100.0); elm_progressbar_value_set(pb, val / 100.0); - s = _size_format(item->mem_size); + s = _size_format(client->mem_size); eina_strbuf_append_printf(buf, "%s / ", s); free(s); s = _size_format(_mem_total); @@ -351,57 +368,68 @@ _proc_stats_item_display(Proc_Stats *item) } static void -_proc_stats_item_update(Eina_List *procs, Proc_Stats *item) +_proc_stats_client_update(Eina_List *procs, Proc_Stats_Client *client) { Proc_Info *proc; Eina_List *l; EINA_LIST_FOREACH(procs, l, proc) { - if (proc->pid == item->pid) + if (proc->pid == client->pid) { - item->cpu_time = item->mem_size = 0; - item->mem_size += proc->mem_size; - item->cpu_time += proc->cpu_time; - _proc_stats_item_children_update(proc->children, item); + client->cpu_time = client->mem_size = 0; + client->mem_size += proc->mem_size; + client->cpu_time += proc->cpu_time; + _proc_stats_client_children_update(proc->children, client); break; } } - _proc_stats_item_display(item); - item->cpu_time_prev = item->cpu_time; + _proc_stats_client_display_update(client); + client->cpu_time_prev = client->cpu_time; } -static Eina_Bool -_proc_stats_timer_cb(void *data) +static void +_proc_stats_thread_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void *msgdata) { - E_Module *module; + Proc_Stats_Module *module; Eina_List *procs, *l; E_Client *ec; Proc_Info *proc; - Proc_Stats *item; + Proc_Stats_Client *client; module = data; + procs = msgdata; EINA_LIST_FOREACH(e_comp->clients, l, ec) { - if (!_proc_stats_item_exists(ec)) - _proc_stats_item_add(ec, module); + if (!_proc_stats_client_exists(ec)) + _proc_stats_client_add(ec); } - procs = proc_info_all_children_get(); - - EINA_LIST_FOREACH(_clients, l, item) + EINA_LIST_FOREACH(module->clients, l, client) { - if (_proc_stats_item_gone(item)) - _proc_stats_item_remove(item); + if (_proc_stats_client_gone(client)) + _proc_stats_client_remove(client); else - _proc_stats_item_update(procs, item); + _proc_stats_client_update(procs, client); } EINA_LIST_FREE(procs, proc) proc_info_free(proc); +} - return 1; +static void +_proc_stats_thread(void *data, Ecore_Thread *thread) +{ + Proc_Stats_Module *module = data; + + while (!ecore_thread_check(thread)) + { + Eina_List *procs = proc_info_all_children_get(); + ecore_thread_feedback(thread, procs); + usleep(1000000 * module->poll_interval); + // e_powersave_sleeper_sleep(module->sleeper, module->poll_interval, EINA_TRUE); + } } E_API E_Module_Api e_modapi = @@ -413,30 +441,42 @@ E_API E_Module_Api e_modapi = E_API int e_modapi_init(E_Module *m) { + Proc_Stats_Module *module; + if (!_memory_total()) return 0; - _proc_stats_timer_cb(m); + _this_module = module = calloc(1, sizeof(Proc_Stats_Module)); + EINA_SAFETY_ON_NULL_RETURN_VAL(module, 0); - _clients_timer = ecore_timer_add(POLL_TIME, _proc_stats_timer_cb, m); + module->e_module = m; + //module->sleeper = e_powersave_sleeper_new(); + module->poll_interval = POLL_INTERVAL; + _proc_stats_thread_feedback_cb(module, NULL, proc_info_all_children_get()); + + module->thread = ecore_thread_feedback_run(_proc_stats_thread, + _proc_stats_thread_feedback_cb, + NULL, NULL, module, 1); return 1; } E_API int e_modapi_shutdown(E_Module *m EINA_UNUSED) { - Proc_Stats *item; + Proc_Stats_Client *client; + Proc_Stats_Module *module = _this_module; - if (_clients_timer) - ecore_timer_del(_clients_timer); + ecore_thread_cancel(module->thread); + ecore_thread_wait(module->thread, 0.2); - _clients_timer = NULL; + //e_powersave_sleeper_free(module->sleeper); - EINA_LIST_FREE(_clients, item) - _proc_stats_item_del(item); + EINA_LIST_FREE(module->clients, client) + _proc_stats_client_del(client); - _clients = NULL; + free(module); + _this_module = NULL; return 1; } @@ -446,3 +486,4 @@ e_modapi_save(E_Module *m EINA_UNUSED) { return 1; } + diff --git a/src/modules/procstats/process.c b/src/modules/procstats/process.c index 5e534eb75..4b5e01298 100644 --- a/src/modules/procstats/process.c +++ b/src/modules/procstats/process.c @@ -154,12 +154,14 @@ _mem_size(Proc_Info *proc) { FILE *f; char buf[1024]; + char path[PATH_MAX]; unsigned int dummy, size, shared, resident, data, text; static int pagesize = 0; if (!pagesize) pagesize = getpagesize(); - f = fopen(eina_slstr_printf("/proc/%d/statm", proc->pid), "r"); + snprintf(path, sizeof(path), "/proc/%i/statm", proc->pid); + f = fopen(path, "r"); if (!f) return; if (fgets(buf, sizeof(buf), f)) @@ -182,32 +184,44 @@ static void _cmd_args(Proc_Info *p, char *name, size_t len) { char line[4096]; + char path[PATH_MAX]; int pid = p->pid; - char *link = ecore_file_readlink(eina_slstr_printf("/proc/%d/exe", pid)); + snprintf(path, sizeof(path), "/proc/%i/exe", pid); + char *link = ecore_file_readlink(path); if (link) { snprintf(name, len, "%s", ecore_file_file_get(link)); free(link); } - FILE *f = fopen(eina_slstr_printf("/proc/%d/cmdline", pid), "r"); + snprintf(path, sizeof(path), "/proc/%i/cmdline", pid); + FILE *f = fopen(path, "r"); if (f) { if (fgets(line, sizeof(line), f)) { + int sz = ftell(f); Eina_Strbuf *buf = eina_strbuf_new(); - const char *n; if (ecore_file_exists(line)) snprintf(name, len, "%s", ecore_file_file_get(line)); - n = line; - while ((n) && (*n) && (*n + 1)) + const char *cp = line; + for (int i = 0; i < sz; i++) { - eina_strbuf_append(buf, n); - n = strchr(n, '\0') + 1; - if ((n) && (*n) && (*n + 1)) eina_strbuf_append(buf, " "); + if (line[i] == '\0') + { + if (*cp) + eina_strbuf_append(buf, cp); + if ((i + 1) < sz) + { + i++; + cp = &line[i]; + if (*cp) + eina_strbuf_append(buf, " "); + } + } } p->arguments = eina_strbuf_release(buf); } @@ -225,9 +239,10 @@ _uid(int pid) { FILE *f; int uid = -1; - char line[1024]; + char line[1024], path[PATH_MAX]; - f = fopen(eina_slstr_printf("/proc/%d/status", pid), "r"); + snprintf(path, sizeof(path), "/proc/%i/status", pid); + f = fopen(path, "r"); if (!f) return -1; while ((fgets(line, sizeof(line), f)) != NULL) @@ -324,6 +339,7 @@ _process_list_linux_get(void) { Eina_List *files, *list; char *n; + char path[PATH_MAX]; Stat st; list = NULL; @@ -336,7 +352,8 @@ _process_list_linux_get(void) if (!pid) continue; - if (!_stat(eina_slstr_printf("/proc/%d/stat", pid), &st)) + snprintf(path, sizeof(path), "/proc/%i/stat", pid); + if (!_stat(path, &st)) continue; if (st.flags & PF_KTHREAD && !proc_info_kthreads_show_get()) @@ -370,13 +387,16 @@ _proc_thread_info(Proc_Info *p) Eina_List *files; char *n; Stat st; + char path[PATH_MAX]; - files = ecore_file_ls(eina_slstr_printf("/proc/%d/task", p->pid)); + snprintf(path, sizeof(path), "/proc/%i/task", p->pid); + files = ecore_file_ls(path); EINA_LIST_FREE(files, n) { int tid = atoi(n); free(n); - if (!_stat(eina_slstr_printf("/proc/%d/task/%d/stat", p->pid, tid), &st)) + snprintf(path, sizeof(path), "/proc/%i/task/%i/stat", p->pid, tid); + if (!_stat(path, &st)) continue; Proc_Info *t = calloc(1, sizeof(Proc_Info)); @@ -401,8 +421,10 @@ Proc_Info * proc_info_by_pid(int pid) { Stat st; + char path[PATH_MAX]; - if (!_stat(eina_slstr_printf("/proc/%d/stat", pid), &st)) + snprintf(path, sizeof(path), "/proc/%i/stat", pid); + if (!_stat(path, &st)) return NULL; Proc_Info *p = calloc(1, sizeof(Proc_Info));