#include "bm_cpu_util.h"
#include "bm_log.h"
-enum heart_cpu_status {
- SERVICE = 0,
- FOREG = 1,
- BACKG = 2,
-};
+#define JIFFY_TO_MS_FACTOR 10 // 1000 / 100
+#define JIFFY_TO_MS(x) ((x) >= UINT_MAX / JIFFY_TO_MS_FACTOR ? UINT_MAX : (x) * JIFFY_TO_MS_FACTOR)
struct app_status {
pid_t pid;
- time_t last_checkpoint; // Need to get usage from this time
time_t used_time; // utime + stime
- enum heart_cpu_status last_status;
+};
+
+struct cpu_time {
+ uint utime;
+ uint stime;
};
static struct timeval last_requested_time;
+static struct cpu_time last_cpu_time;
static GDBusConnection *dbus_connection;
static GHashTable *running_app_list; // Key(appid), Val(app_status)
return is_running;
}
+int get_cpu_time(struct cpu_time *cpu_time)
+{
+ int ret;
+ FILE *fp = NULL;
+
+ fp = fopen("/proc/stat", "r");
+ if (!fp) {
+ _E("fopen failed : %m");
+ return errno;
+ }
+
+ ret = fscanf(fp, "%*s %u %*s %u", &(cpu_time->utime), &(cpu_time->stime));
+ fclose(fp);
+
+ if (ret < 2) {
+ _E("fscanf failed (%d)", ret);
+ return EIO;
+ }
+
+ return 0;
+}
+
int deinit()
{
ENTER;
{
ENTER;
+ int ret;
GError *g_err = NULL;
if (gettimeofday(&last_requested_time, NULL) != 0) {
goto failed;
}
+ ret = get_cpu_time(&last_cpu_time);
+ if (ret != 0) {
+ _E("Failed to get CPU time (%d)", ret);
+ goto failed;
+ }
+
dbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &g_err);
if (!dbus_connection) {
_E("g_bus_get_sync failed : %s", g_err->message ? g_err->message : NULL);
bm_cpu_st *usage = NULL;
struct timeval tv;
+ struct cpu_time cur_cpu_time;
GError *g_err = NULL;
GDBusMessage *msg_req, *msg_reply;
char query[128];
/* DB row */
- unsigned int time;
const char *appid;
const char *data;
unsigned int utime, stime, pid, status;
return BM_PLUGIN_ERROR_OUT_OF_MEMORY;
}
+ /* Get total CPU time */
+ ret = get_cpu_time(&cur_cpu_time);
+ if (ret != 0) {
+ _E("Failed to get CPU time (%d)", ret);
+
+ EXIT;
+ return BM_PLUGIN_ERROR_NO_DATA;
+ }
+
+ /* Check total CPU usage */
+ if (cur_cpu_time.utime < last_cpu_time.utime || cur_cpu_time.stime < last_cpu_time.stime) {
+ _E("Negative CPU usage. Nothing to return");
+
+ EXIT;
+ return BM_PLUGIN_ERROR_NO_DATA;
+ }
+
+ if (cur_cpu_time.utime == last_cpu_time.utime && cur_cpu_time.stime == last_cpu_time.stime) {
+ _I("System doesn't use CPU. Nothing to return");
+
+ EXIT;
+ return BM_PLUGIN_ERROR_NO_DATA;
+ }
+
/* Request for resourced to update HEART-CPU DB */
msg_req = g_dbus_message_new_method_call(
"org.tizen.resourced",
return BM_PLUGIN_ERROR_OUT_OF_MEMORY;
}
+ /* Update total CPU time */
+ usage->utime = JIFFY_TO_MS(cur_cpu_time.utime - last_cpu_time.utime);
+ usage->stime = JIFFY_TO_MS(cur_cpu_time.stime - last_cpu_time.stime);
+
+ _D("Total CPU usage : %u", JIFFY_TO_MS(usage->utime + usage->stime));
+
/* Read data from HEART-CPU DB */
_I("Gather CPU usage : %ld ~ %ld", last_requested_time.tv_sec, tv.tv_sec);
- snprintf(query, 128, "SELECT time,appid,data FROM cpu WHERE time >= %ld", last_requested_time.tv_sec);
+ snprintf(query, 128, "SELECT appid,data FROM cpu WHERE time >= %ld", last_requested_time.tv_sec);
ret = sqlite3_prepare_v2(db, query, -1, &stmt, 0);
while (sqlite3_step(stmt) == SQLITE_ROW) {
- time = sqlite3_column_int(stmt, 0);
- appid = (const char *)sqlite3_column_text(stmt, 1);
- data = (const char *)sqlite3_column_text(stmt, 2);
+ appid = (const char *)sqlite3_column_text(stmt, 0);
+ data = (const char *)sqlite3_column_text(stmt, 1);
sscanf(data, "%u %u %u %u", &utime, &stime, &pid, &status);
- //_D("time(%u), appid(%s), utime(%u), stime(%u), pid(%u), status(%u)", time, appid, utime, stime, pid, status);
+ //_D("appid(%s), utime(%u), stime(%u), pid(%u), status(%u)", appid, utime, stime, pid, status);
/* Ignore terminated app */
if (!is_running_app(appid)) {
goto clean_atm;
}
new_app_status->pid = pid;
- new_app_status->last_checkpoint = time;
- new_app_status->used_time = utime + stime;
- new_app_status->last_status = status;
+ new_app_status->used_time = JIFFY_TO_MS(utime + stime);
g_hash_table_insert(running_app_list, g_strdup(appid), new_app_status);
continue;
}
if (app_status->pid != pid) {
_D("%s is restarted", appid);
app_status->pid = pid;
- app_status->last_checkpoint = time;
- app_status->used_time = utime + stime;
- app_status->last_status = status;
+ app_status->used_time = JIFFY_TO_MS(utime + stime);
continue;
}
/* Ignore CPU unused app */
- elapsed = utime + stime - app_status->used_time;
+ elapsed = JIFFY_TO_MS(utime + stime) - app_status->used_time;
if (elapsed <= 0) {
_D("%s doesn't use CPU. Ignore it", appid);
continue;
}
- /* Accumulate used time */
- _D("%s uses CPU (+%d)", appid, elapsed);
- usage->cpuTicks += elapsed;
- switch (app_status->last_status) {
- case FOREG:
- usage->cpuTimeForeground += elapsed;
- break;
- case BACKG:
- case SERVICE:
- usage->cpuTimeBackground += elapsed;
- break;
- }
+ _D("%s uses CPU (+%d ms)", appid, elapsed);
/* Insert the app using CPU in the ATM list */
if (!g_slist_find_custom(usage->atm_list, appid, find_app_time)) {
ret = BM_PLUGIN_ERROR_OUT_OF_MEMORY;
goto clean_atm;
}
- app_time_map->time = tv.tv_sec - app_status->last_checkpoint;
- if (app_time_map->time <= 0)
- app_time_map->time = 1;
+ app_time_map->time = elapsed;
usage->atm_list = g_slist_append(usage->atm_list, app_time_map);
}
/* Update app status */
- app_status->used_time = utime + stime;
- app_status->last_status = status;
+ app_status->used_time += elapsed;
}
/* Update all running apps with current value */
continue;
}
- app_status->last_checkpoint = tv.tv_sec;
-
/* Ignore CPU unused app */
- elapsed = cpu_usage->utime + cpu_usage->stime - app_status->used_time;
+ elapsed = JIFFY_TO_MS(cpu_usage->utime + cpu_usage->stime) - app_status->used_time;
+ free(cpu_usage);
if (elapsed <= 0) {
_D("%s doesn't use CPU. Ignore it", appid);
continue;
}
- /* Update CPU time */
- _D("%s uses CPU (+%d)", appid, elapsed);
- usage->cpuTicks += elapsed;
- switch (app_status->last_status) {
- case FOREG:
- usage->cpuTimeForeground += elapsed;
- break;
- case BACKG:
- case SERVICE:
- usage->cpuTimeBackground += elapsed;
- break;
- }
+ _D("%s uses CPU (+%d ms)", appid, elapsed);
/* Insert the app using CPU in the ATM list */
if (!g_slist_find_custom(usage->atm_list, appid, find_app_time)) {
ret = BM_PLUGIN_ERROR_OUT_OF_MEMORY;
goto clean_atm;
}
- app_time_map->time = tv.tv_sec - last_requested_time.tv_sec;
- if (app_time_map->time <= 0)
- app_time_map->time = 1;
+ app_time_map->time = elapsed;
usage->atm_list = g_slist_append(usage->atm_list, app_time_map);
}
- app_status->used_time = cpu_usage->utime + cpu_usage->stime;
-
- free(cpu_usage);
+ app_status->used_time += elapsed;
}
/* Update last requested time */
last_requested_time.tv_sec = tv.tv_sec;
last_requested_time.tv_usec = tv.tv_usec;
+ /* Update last CPU time */
+ last_cpu_time.utime = cur_cpu_time.utime;
+ last_cpu_time.stime = cur_cpu_time.stime;
+
/* Return result */
usage_head->cpu_data_list = g_slist_append(usage_head->cpu_data_list, usage);
*handle = usage_head;