return fwrite_str(path, digit_buf);
}
+int fwrite_ulong(const char *path, const unsigned long number)
+{
+ _cleanup_free_ char *digit_buf = NULL;
+ int ret;
+
+ ret = asprintf(&digit_buf, "%lu", number);
+ ret_value_errno_msg_if(ret < 0, -ENOMEM,
+ "sprintf failed\n");
+
+ return fwrite_str(path, digit_buf);
+}
+
int fread_str(const char *path, char **str)
{
_cleanup_fclose_ FILE *f = NULL;
return RESOURCED_ERROR_NONE;
}
+int fread_ulong(const char *path, unsigned long *number)
+{
+ _cleanup_fclose_ FILE *f = NULL;
+ int ret;
+
+ f = fopen(path, "r");
+ ret_value_errno_msg_if(!f, -errno,
+ "Fail to open %s file.", path);
+
+ ret = fscanf(f, "%lu", number);
+ ret_value_errno_msg_if(ret == EOF, -errno,
+ "Fail to read file\n");
+
+ return RESOURCED_ERROR_NONE;
+}
+
int fwrite_array(const char *path, const void *array,
const size_t size_of_elem,
const size_t numb_of_elem)
int fwrite_uint(const char *path, const u_int32_t number);
+int fwrite_ulong(const char *path, const unsigned long number);
+
int fread_str(const char *path, char **str);
int fread_int(const char *path, int32_t *number);
int fread_uint(const char *path, u_int32_t *number);
+int fread_ulong(const char *path, unsigned long *number);
+
int fwrite_array(const char *path, const void *array,
const size_t size_of_elem,
const size_t numb_of_elem);
struct resourced_appinfo *ai;
struct proc_program_info *program;
struct proc_memory_state memory;
-
+ unsigned long starttime;
};
int proc_get_freezer_status(void);
return fread_uint(app_info_node, data); \
}
+#define DEFINE_PROC_RUNTIME_APP_INFO_WRITE_ULONG(node) \
+ int proc_runtime_app_info_write_##node(const char *path, \
+ unsigned long data) \
+ { \
+ char app_info_node[PATH_MAX] = ""; \
+ \
+ assert(path); \
+ \
+ snprintf(app_info_node, PATH_MAX, "%s/"#node"", path); \
+ \
+ return fwrite_ulong(app_info_node, data); \
+ }
+
+#define DEFINE_PROC_RUNTIME_APP_INFO_READ_ULONG(node) \
+ int proc_runtime_app_info_read_##node(const char *path, \
+ unsigned long *data) \
+ { \
+ char app_info_node[PATH_MAX] = ""; \
+ \
+ assert(path); \
+ assert(data); \
+ \
+ snprintf(app_info_node, PATH_MAX, "%s/"#node"", path); \
+ \
+ return fread_ulong(app_info_node, data); \
+ }
+
#define DEFINE_PROC_RUNTIME_APP_INFO_REMOVE(node) \
int proc_runtime_app_info_remove_##node(const char *path) \
{ \
DEFINE_PROC_RUNTIME_APP_INFO_READ_INT32(type);
DEFINE_PROC_RUNTIME_APP_INFO_WRITE_STR(pkgname);
DEFINE_PROC_RUNTIME_APP_INFO_READ_STR(pkgname);
+DEFINE_PROC_RUNTIME_APP_INFO_WRITE_ULONG(starttime);
+DEFINE_PROC_RUNTIME_APP_INFO_READ_ULONG(starttime);
DEFINE_PROC_RUNTIME_APP_INFO_REMOVE(appid);
DEFINE_PROC_RUNTIME_APP_INFO_REMOVE(procs);
DEFINE_PROC_RUNTIME_APP_INFO_REMOVE(state);
DEFINE_PROC_RUNTIME_APP_INFO_REMOVE(type);
DEFINE_PROC_RUNTIME_APP_INFO_REMOVE(pkgname);
+DEFINE_PROC_RUNTIME_APP_INFO_REMOVE(starttime);
+
static int proc_runtime_app_info_write_procs(const char *path, pid_list child_list)
{
if (ret < 0)
return ret;
+ ret = proc_runtime_app_info_write_starttime(runtime_app_info_path, pai->starttime);
+ if (ret < 0)
+ return ret;
+
if (!pai->program)
return 0;
if (ret < 0 && ret != -ENOENT)
goto finish;
+ ret = proc_runtime_app_info_remove_starttime(runtime_app_info_path);
+ if (ret < 0 && ret != -ENOENT)
+ goto finish;
+
finish:
if (rmdir(runtime_app_info_path) < 0)
return -errno;
enum proc_state state)
{
struct proc_app_info *pai;
+ unsigned long uptime = 0;
+ int ret;
if (!appid || !pkgid) {
_E("Each app should have appid and pkgid");
if (categories)
pai->categories = categories;
- pai->program = proc_add_program_list(type, pai, pkgid, false);
-
+ if (pid > 0) {
+ pai->program = proc_add_program_list(type, pai, pkgid, false);
+ if (!pai->starttime) {
+ ret = proc_get_uptime(&uptime);
+ if (ret)
+ _E("Failed to get uptime");
+ else
+ pai->starttime = uptime;
+ }
+ }
return pai;
}
struct proc_app_info *proc_add_app_info(const char *appid,
if (ret < 0)
return ret;
+ ret = proc_runtime_app_info_read_starttime(path, &pai->starttime);
+ if (ret < 0)
+ return ret;
+
ret = proc_runtime_app_info_read_procs(path, &pai->childs);
if (ret < 0 && ret != -ENOENT)
return ret;
GSList *giter;
char *appid;
struct proc_app_info *pai;
- unsigned long uptime, utime, stime, starttime;
+ unsigned long uptime, utime, stime, deltatime, starttime;
int ret;
GVariantBuilder builder, *sub_builder;
if (proc_get_cpu_time(pai->main_pid, &utime, &stime, &starttime) != RESOURCED_ERROR_NONE)
continue;
appid = pai->appid;
- percent = 100 * (((utime + stime) * 1000 / HZ) / (uptime - (starttime / HZ)));
+
+ deltatime = uptime - pai->starttime;
+ if (deltatime == 0)
+ percent = 0;
+ else
+ percent = (utime + stime) / deltatime;
g_variant_builder_add(sub_builder, "(su)", appid, percent);
}
int ret, type;
char *appid;
struct proc_app_info *pai;
- unsigned long uptime, utime, stime, starttime;
+ unsigned long uptime, utime, stime, deltatime, starttime;
GVariantBuilder builder, *sub_builder;
g_variant_get(params, "(i)", &type);
if (proc_get_cpu_time(pai->main_pid, &utime, &stime, &starttime) != RESOURCED_ERROR_NONE)
continue;
appid = pai->appid;
- percent = (((utime + stime)*100 /HZ) / (uptime - (starttime/HZ)));
+
+ /*
+ * cpu usage can be calculated using total usage of stime and utime out of delta time.
+ * cpu usage = (utime + stime ticks) / (current uptime - process start time) * 100 percentage
+ * = (utime + stime seconds) / (current uptime - process start time)
+ *
+ * Meanwhile, delta time between uptime and starttime should be checked
+ * whether it is zero or not.
+ * If delta time is zero, it can cause "divided by zero" fatal error.
+ */
+ deltatime = uptime - pai->starttime;
+ if (deltatime == 0)
+ percent = 0;
+ else
+ percent = (utime + stime) / deltatime;
g_variant_builder_add(sub_builder, "(su)", appid, percent);
}