From: Vitaliy Cherepanov Date: Thu, 14 Apr 2016 08:10:12 +0000 (+0300) Subject: Implement protocol version 4.2 X-Git-Tag: accepted/tizen/common/20160809.184206^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b185723f0e34b58a56d41b71f412c739d7d3650c;p=platform%2Fcore%2Fsystem%2Fswap-manager.git Implement protocol version 4.2 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 --- 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 #include -#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 #include #include +#include #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 }