summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaliy Cherepanov <v.cherepanov@samsung.com>2016-04-14 11:10:12 +0300
committerAnatolii Nikulin <nikulin.a@samsung.com>2016-08-09 15:34:24 +0300
commitb185723f0e34b58a56d41b71f412c739d7d3650c (patch)
treec6f52e9914dd158bc7b2b70aea9b3b0a1a6e2d23
parent0540003ef8b9f2a0873ab669e23d3121a68c9861 (diff)
downloadswap-manager-b185723f0e34b58a56d41b71f412c739d7d3650c.tar.gz
swap-manager-b185723f0e34b58a56d41b71f412c739d7d3650c.tar.bz2
swap-manager-b185723f0e34b58a56d41b71f412c739d7d3650c.zip
Depends on modules: Implement protocol version 4.2 add 3D and GEM pss memory to system info. Change-Id: I5b64836a5efb8259f3128af1acbba5b21fccb41f Signed-off-by: Vitaliy Cherepanov <v.cherepanov@samsung.com>
-rw-r--r--daemon/da_protocol.h3
-rw-r--r--daemon/daemon.h1
-rw-r--r--daemon/main.c5
-rw-r--r--daemon/sys_stat.c428
-rw-r--r--daemon/sys_stat.h5
5 files changed, 360 insertions, 82 deletions
diff --git a/daemon/da_protocol.h b/daemon/da_protocol.h
index 6de4b19..a27328e 100644
--- a/daemon/da_protocol.h
+++ b/daemon/da_protocol.h
@@ -37,7 +37,7 @@
#include <linux/input.h>
#include <assert.h>
-#define PROTOCOL_VERSION "4.1"
+#define PROTOCOL_VERSION "4.2"
#include "da_msg_ids.h"
@@ -360,6 +360,7 @@ struct system_info_t {
// system_memory
uint64_t system_memory_used;
+ uint64_t system_total_gem_memory;
// system_processes
uint32_t count_of_inst_processes;
diff --git a/daemon/daemon.h b/daemon/daemon.h
index cc31438..4424d15 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -110,6 +110,7 @@ typedef struct
int brightness;
int voltage;
int procmeminfo;
+ FILE *gem_memory;
FILE *video;
FILE *procstat;
FILE *networkstat;
diff --git a/daemon/main.c b/daemon/main.c
index 8d148f5..e9e47f6 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -90,6 +90,7 @@ __da_manager manager =
.brightness = -1,
.voltage = -1,
.procmeminfo = -1,
+ .gem_memory = NULL,
.video = NULL,
.procstat = NULL,
.networkstat = NULL,
@@ -459,7 +460,7 @@ int main()
return 1;
//init all file descriptors
- init_system_file_descriptors();
+ init_sys_stat();
//daemon work
//FIX ME remove samplingThread it is only for debug
//samplingThread(NULL);
@@ -468,7 +469,7 @@ int main()
stop_all();
finalizeManager();
- close_system_file_descriptors();
+ uninit_sys_stat();
//DO NOT USE THIS FUNCTION FOR RELEASE IT IS TOO SLOW
#ifdef MALLOC_DEBUG_LEVEL
diff --git a/daemon/sys_stat.c b/daemon/sys_stat.c
index 8a6c50a..9bb930c 100644
--- a/daemon/sys_stat.c
+++ b/daemon/sys_stat.c
@@ -46,6 +46,7 @@
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
+#include <sys/utsname.h>
#include "da_protocol.h"
#include "da_data.h"
@@ -79,7 +80,12 @@
#define CPUMHZ "cpu MHz"
#define DA_PROBE_TIZEN_SONAME "da_probe_tizen.so"
-#define DA_PROBE_OSP_SONAME "da_probe_osp.so"
+#define DA_PROBE_OSP_SONAME "da_probe_osp.so"
+
+#define STR_SGX_PATH "/dev/pvrsrvkm"
+
+#define STR_3D_PATH1 "/dev/mali"
+#define STR_3D_PATH2 "/dev/kgsl-3d0"
// define for correct difference of system feature vars
#define val_diff(v_new, v_old) ((v_new < v_old) ? v_new : v_new - v_old)
@@ -378,8 +384,12 @@ typedef struct {
int numofthread;
long dummy;
unsigned long long start_time;
+ unsigned long size;
unsigned long vir_mem;
- unsigned long sh_mem;
+ unsigned long sh_mem_clean;
+ unsigned long sh_mem_dirty;
+ unsigned long gem_pss;
+ unsigned long graphic_3d;
long res_memblock;
unsigned long pss;
float cpu_load;
@@ -585,20 +595,306 @@ static int parse_proc_stat_file_bypid(char *path, proc_t* P, int is_inst_process
return 0;
}
+struct geminfo {
+ struct geminfo *next;
+ pid_t tgid;
+ unsigned rss_size;
+ unsigned pss_size;
+ unsigned hcount;
+};
+
+static void init_gem_memory()
+{
+ manager.fd.gem_memory = fopen(GEM_FILE, "r");
+}
+
+#define NUM_GEM_FIELD 6
+
+static struct geminfo *find_geminfo(pid_t tgid, struct geminfo *gilist)
+{
+ struct geminfo *gi;
+ for (gi = gilist; gi; gi = gi->next) {
+ if (gi->tgid == tgid)
+ return gi;
+
+ }
+ return NULL;
+}
+
+static void free_geminfo(struct geminfo *gilist)
+{
+ struct geminfo *g;
+ while (gilist) {
+ g = gilist->next;
+ free(gilist);
+ gilist = g;
+ }
+}
+
+static struct geminfo *read_geminfo(FILE *fp)
+{
+ struct geminfo *tgeminfo = NULL;
+ char line[BUFFER_MAX];
+ unsigned int pid, tgid, handle, refcount, hcount;
+ unsigned gem_size;
+
+ if (fgets(line, BUFFER_MAX, fp) == NULL)
+ goto exit;
+
+ if (sscanf(line, "%d %d %d %d %d 0x%x",
+ &pid, &tgid, &handle, &refcount,
+ &hcount, &gem_size) != NUM_GEM_FIELD)
+ goto exit;
+
+ if (hcount == 0)
+ goto exit;
+
+ tgeminfo = malloc(sizeof(*tgeminfo));
+ if (tgeminfo == NULL) {
+ LOGE("allocation error\n");
+ goto exit;
+ }
+
+ tgeminfo->tgid = tgid;
+ tgeminfo->hcount = hcount;
+ tgeminfo->rss_size = gem_size;
+ tgeminfo->pss_size = gem_size/hcount;
+
+exit:
+ return tgeminfo;
+}
+
+static struct geminfo *load_geminfo(void)
+{
+ struct geminfo *ginfo;
+ struct geminfo *gilist = NULL;
+
+ FILE *gem_fp;
+ char line[BUFFER_MAX];
+
+ gem_fp = manager.fd.gem_memory;
+
+ if (gem_fp == NULL)
+ goto exit;
+
+ rewind(gem_fp);
+ fflush(gem_fp);
+
+ /* skeep first line */
+ if (fgets(line, BUFFER_MAX, gem_fp) == NULL)
+ goto exit;
+
+ while ((ginfo = read_geminfo(gem_fp)) != NULL) {
+ if (gilist) {
+ if (ginfo->tgid == gilist->tgid) {
+ /* update current process */
+ gilist->pss_size += ginfo->pss_size;
+ gilist->rss_size += ginfo->rss_size;
+ free(ginfo);
+ continue;
+ } else {
+ /* search and update process */
+ struct geminfo *exist;
+ exist = find_geminfo(ginfo->tgid, gilist);
+ if (exist) {
+ exist->pss_size += ginfo->pss_size;
+ exist->rss_size += ginfo->rss_size;
+ free(ginfo);
+ continue;
+ }
+ }
+ }
+ /* add new item */
+ ginfo->next = gilist;
+ gilist = ginfo;
+ }
+
+exit:
+ return gilist;
+}
+
+static uint64_t total_gem_memory(void)
+{
+ FILE *gem_fp = manager.fd.gem_memory;
+ unsigned total_gem_mem = 0;
+ unsigned name, size, handles, refcount;
+ char line[MIDDLE_BUFFER];
+
+ if (gem_fp == NULL)
+ return 0;
+
+ rewind(gem_fp);
+ fflush(gem_fp);
+
+ if (manager.fd.gem_memory == NULL)
+ return 0;
+
+ if (gem_fp == NULL) {
+ LOG_ONCE_W("cannot open gem file <%s>\n", GEM_FILE);
+ return 0;
+ }
+
+ /* skeep head line */
+ if (fgets(line, sizeof(line), gem_fp) == NULL)
+ return 0;
+
+ /* get data */
+ while (fgets(line, sizeof(line), gem_fp) != NULL)
+ if (sscanf(line, "%d %d %d %d\n",
+ &name, &size, &handles, &refcount) == 4)
+ total_gem_mem += size;
+
+ return total_gem_mem;
+}
+
+static int ignore_smaps_field = 0;
+
+void init_read_mapinfo(void)
+{
+ struct utsname buf;
+ int ret;
+
+ ret = uname(&buf);
+
+ if (!ret) {
+ if (buf.release[0] == '3') {
+ char *pch;
+ char str[3];
+ int sub_version;
+ pch = strstr(buf.release, ".");
+ strncpy(str, pch+1, 2);
+ sub_version = atoi(str);
+
+ if (sub_version >= 10) {
+ /* Referenced, Anonymous, AnonHugePages,
+ * Swap, KernelPageSize, MMUPageSize,
+ * Locked, VmFlags
+ */
+ ignore_smaps_field = 8;
+ } else {
+ /* Referenced, Anonymous, AnonHugePages,
+ * Swap, KernelPageSize, MMUPageSize,
+ * Locked
+ */
+ ignore_smaps_field = 7;
+ }
+ } else {
+ /* Referenced, Swap, KernelPageSize, MMUPageSize */
+ ignore_smaps_field = 4;
+ }
+ }
+}
+/* 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /android/lib/libcomposer.so
+ * 012345678901234567890123456789012345678901234567890123456789
+ * 0 1 2 3 4 5
+ */
+
+#define NAME_OFFSET 49
+int read_mapinfo_section(FILE* fp, proc_t *proc)
+{
+ char* line;
+ int len;
+ int tmp;
+ int rest_line;
+ char buf[LARGE_BUFFER];
+
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0)
+ return -EOF;
+
+ len = strlen(buf);
+ if (len < 1)
+ return 0;
+
+ if (len < NAME_OFFSET + 1) {
+ strncpy(proc->command, "[anon]", strlen("[anon]")+1);
+ } else {
+ len = strnlen(buf + NAME_OFFSET, sizeof(buf) - NAME_OFFSET);
+ strncpy(proc->command, buf + NAME_OFFSET, len + 1);
+ }
+
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if (sscanf(buf, "Size: %lu kB", &proc->size) != 1) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if (sscanf(buf, "Rss: %d kB", &tmp) != 1) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if (sscanf(buf, "Pss: %lu kB", &proc->pss) == 1)
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if (sscanf(buf, "Shared_Clean: %lu kB", &proc->sh_mem_clean) != 1) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if (sscanf(buf, "Shared_Dirty: %lu kB", &proc->sh_mem_dirty) != 1) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if (sscanf(buf, "Private_Clean: %d kB", &tmp) != 1) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if ((line = fgets(buf, sizeof(buf), fp)) == 0) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+ if (sscanf(buf, "Private_Dirty: %d kB", &tmp) != 1) {
+ LOGE("Get section error\n");
+ goto oops;
+ }
+
+ rest_line = ignore_smaps_field;
+ while (rest_line-- && (line = fgets(buf, sizeof(buf), fp))) {
+ if (sscanf(buf, "PSwap: %d kB", &tmp) == 1)
+ rest_line++;
+ }
+
+ return 0;
+oops:
+ LOGE("Get section error\n");
+ return -1;
+}
+
+
// return 0 for normal case
// return negative value for error case
-static int parse_proc_smaps_file_bypid(char *path, proc_t* P)
+static int parse_proc_smaps_file_bypid(char *path, proc_t *P)
{
#define MIN_SMAP_BLOCKLINE 50
char filename[PROCPATH_MAX];
- char buf[MIDDLE_BUFFER];
- char numbuf[SMALL_BUFFER];
+ proc_t proc_tmp;
FILE* fp;
// reset pss size of proc_t
P->pss = 0;
- P->sh_mem = 0;
+ P->sh_mem_clean = 0;
+ P->sh_mem_dirty = 0;
+ P->graphic_3d = 0;
+ P->gem_pss = 0;
// read from smaps file
snprintf(filename, sizeof(filename), "%s/smaps", path);
@@ -608,70 +904,19 @@ static int parse_proc_smaps_file_bypid(char *path, proc_t* P)
return -1;
}
- if(unlikely(probe_so_size == 0)) // probe so size is not abtained
- {
- int is_probe_so = 0;
- while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
- {
- if(strncmp(buf, "Pss:", 4) == 0) // line is started with "Pss:"
- {
- sscanf(buf, "Pss:%s kB", numbuf);
- P->pss += atoi(numbuf);
- if(is_probe_so == 1)
- {
- probe_so_size += atoi(numbuf);
- is_probe_so = 0; // reset search flag
- }
- }
- else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
- {
- char *p = strstr(buf, ":");
- if (p != 0) {
- sscanf(p, ":%s kB", numbuf);
- P->sh_mem += atoi(numbuf);
- }
-
- }
- else // not Pss line
- {
- if (is_probe_so == 0 && strlen(buf) > MIN_SMAP_BLOCKLINE)
- {
- // first we find probe so section
- if(strstr(buf, DA_PROBE_TIZEN_SONAME) != NULL ||
- strstr(buf, DA_PROBE_OSP_SONAME) != NULL)
- {
- // found probe.so
- is_probe_so = 1;
- }
- else
- {
- // do nothing
- }
- }
- else
- {
- // do nothing
- }
- }
- }
- }
- else // we know about probe.so size already
- {
- while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
- {
- if(strncmp(buf, "Pss:", 4) == 0)
- {
- sscanf(buf, "Pss:%s kB", numbuf);
- P->pss += atoi(numbuf);
- }
- else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
- {
- char *p = strstr(buf, ":");
- if (p != 0) {
- sscanf(p, ":%s kB", numbuf);
- P->sh_mem += atoi(numbuf);
- }
- }
+ while (read_mapinfo_section(fp, &proc_tmp) == 0) {
+ if (strstr(proc_tmp.command, DA_PROBE_TIZEN_SONAME)) {
+ /* We should skeep this section */
+ continue;
+ } else if (strstr(proc_tmp.command, STR_SGX_PATH)) {
+ P->graphic_3d += proc_tmp.pss;
+ } else if (strstr(proc_tmp.command, STR_3D_PATH1) ||
+ strstr(proc_tmp.command, STR_3D_PATH2)) {
+ P->graphic_3d += proc_tmp.size;
+ } else {
+ P->pss += proc_tmp.pss;
+ P->sh_mem_clean += proc_tmp.sh_mem_clean;
+ P->sh_mem_dirty += proc_tmp.sh_mem_dirty;
}
}
// TODO that probe_so_size calculation maybe wrong. check it. fix it
@@ -679,7 +924,8 @@ static int parse_proc_smaps_file_bypid(char *path, proc_t* P)
// convert to bytes
P->pss *= 1024;
- P->sh_mem *= 1024;
+ P->sh_mem_clean *= 1024;
+ P->sh_mem_dirty *= 1024;
fclose(fp);
@@ -695,6 +941,10 @@ static int update_process_data(procNode **prochead, pid_t* pidarray, int pidcoun
int i, ret = 0, is_new_node = 0;
char buf[PROCPATH_MAX];
procNode* procnode;
+ struct geminfo *gilist;
+
+
+ gilist = load_geminfo();
for(i = 0; i < pidcount; i++)
{
@@ -753,11 +1003,21 @@ static int update_process_data(procNode **prochead, pid_t* pidarray, int pidcoun
// impossible
}
+ /* add gem info */
+ if (gilist != NULL) {
+ struct geminfo *gi = find_geminfo(pidarray[i], gilist);
+ if (gi != NULL) {
+ //procnode->proc_data.gem_rss = gi->rss_size;
+ procnode->proc_data.gem_pss = gi->pss_size;
+ }
+ }
+
}
del_notfound_node(prochead);
reset_found_node(*prochead);
exit:
+ free_geminfo(gilist);
return ret;
}
@@ -773,8 +1033,7 @@ static int update_system_cpu_frequency(int cur_index)
{
FILE* fp;
num_of_freq = 0;
- if((fp = fopen(CPUNUM_OF_FREQ, "r")) != NULL)
- {
+ if((fp = fopen(CPUNUM_OF_FREQ, "r")) != NULL) {
while(fgets(buf, SMALL_BUFFER, fp) != NULL)
{
num_of_freq++;
@@ -2070,8 +2329,10 @@ int get_system_info(struct system_info_t *sys_info)
}
}
- if (IS_OPT_SET(FL_SYSTEM_MEMORY))
+ if (IS_OPT_SET(FL_SYSTEM_MEMORY)) {
sys_info->system_memory_used = sysmemused;
+ sys_info->system_total_gem_memory = total_gem_memory();
+ }
LOGI_th_samp("Fill result structure\n");
@@ -2197,8 +2458,10 @@ static void ftest_and_close(FILE **fd)
#define dtest_and_close(fd) do {LOGI("CLOSE " STR_VALUE(fd) "\n");test_and_close(fd);} while(0)
#define dftest_and_close(fd) do {LOGI("CLOSE " STR_VALUE(fd) "\n");ftest_and_close(fd);} while(0)
-void close_system_file_descriptors(void)
+void uninit_sys_stat(void)
{
+ dftest_and_close(&manager.fd.gem_memory);
+
dtest_and_close(&manager.fd.brightness);
dtest_and_close(&manager.fd.voltage);
dtest_and_close(&manager.fd.procmeminfo);
@@ -2209,9 +2472,11 @@ void close_system_file_descriptors(void)
dftest_and_close(&manager.fd.diskstats);
}
-int init_system_file_descriptors(void)
+int init_sys_stat(void)
{
//inits
+ init_gem_memory();
+
init_brightness_status();
init_voltage_status();
init_update_system_memory_data();
@@ -2221,6 +2486,8 @@ int init_system_file_descriptors(void)
init_network_stat();
init_disk_stat();
+ if (manager.fd.gem_memory < 0)
+ LOGW("gem file not found\n");
if (manager.fd.brightness < 0)
LOGW("brightness file not found\n");
if (manager.fd.voltage < 0)
@@ -2236,6 +2503,9 @@ int init_system_file_descriptors(void)
LOGW("networkstat file not found\n");
if (manager.fd.diskstats == NULL)
LOGW("diskstat file not found\n");
+
+ init_read_mapinfo();
+
return 0;
}
@@ -2378,6 +2648,7 @@ struct msg_data_t *pack_system_info(struct system_info_t *sys_info)
/* memory */
pack_int64(p, sys_info->system_memory_used);
+// pack_int64(p, sys_info->system_total_gem_memory);
/* inst process / target process */
if (IS_OPT_SET(FL_SYSTEM_PROCESS)) {
@@ -2388,8 +2659,11 @@ struct msg_data_t *pack_system_info(struct system_info_t *sys_info)
pack_float(p, proc->proc_data.cpu_load);
pack_int64(p, (uint64_t)proc->proc_data.vir_mem);
pack_int64(p, (uint64_t)proc->proc_data.res_memblock);
- pack_int64(p, (uint64_t)proc->proc_data.sh_mem);
+ pack_int64(p, (uint64_t)(proc->proc_data.sh_mem_dirty +
+ proc->proc_data.sh_mem_clean));
pack_int64(p, (uint64_t)proc->proc_data.pss);
+ pack_int64(p, (uint64_t)proc->proc_data.gem_pss);
+ pack_int64(p, (uint64_t)proc->proc_data.graphic_3d);
/* TODO total alloc for not ld preloaded processes */
pack_int64(p, target_get_total_alloc(proc->proc_data.pid));
diff --git a/daemon/sys_stat.h b/daemon/sys_stat.h
index 237ecbc..68fe17f 100644
--- a/daemon/sys_stat.h
+++ b/daemon/sys_stat.h
@@ -52,6 +52,7 @@ extern "C" {
#define CPUFREQ_FILE "cpufreq/stats/time_in_state"
#define CPUNUM_OF_FREQ CPUDIR"/cpu0/"CPUFREQ_FILE
+#define GEM_FILE "/sys/kernel/debug/dri/0/gem_info"
#define UMSFD "/mnt/ums"
#define MMCBLKFD "/dev/mmcblk1"
@@ -90,8 +91,8 @@ int finalize_system_info(void);
int fill_target_info(struct target_info_t *target_info);
-int init_system_file_descriptors(void);
-void close_system_file_descriptors(void);
+int init_sys_stat(void);
+void uninit_sys_stat(void);
int sys_stat_prepare(void);
#ifdef __cplusplus
}