/* * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Flora License, Version 1.1 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://floralicense.org/license/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "process.h" #include "clock.h" #include "sys-stats.h" #include "err-check.h" #include "procfs.h" #include "appinfo-provider.h" #include "json-schema-defs.h" static struct sys_stats sys; static int pagesize; static float timescale; int process_get_memory_usage(struct process *proc, int *usage) { ON_NULL_RETURN_VAL(proc, -1); ON_NULL_RETURN_VAL(usage, -1); *usage = proc->memory_used; return 0; } int process_get_cpu_usage(struct process *proc, unsigned long long *usage) { ON_NULL_RETURN_VAL(proc, -1); ON_NULL_RETURN_VAL(usage, -1); *usage = proc->frame_ticks_used; return 0; } int process_update(struct process *proc) { struct procfs_process_stat info; unsigned long long ticks; if (procfs_read_process_stat(proc->pid, &info) != 0) { return -1; } ticks = info.stime + info.utime; proc->frame_ticks_used = ticks - proc->total_ticks_used; proc->total_ticks_used = ticks; proc->memory_used = info.rss * pagesize / 1024; float now = clock_monotonic_get(); proc->frame_time_inverted = 1.0f / (now - proc->update_time); proc->update_time = now; return 0; } void process_init_process(int pid, struct process *proc) { memset(proc, 0x0, sizeof(struct process)); proc->pid = pid; } int process_get_pid(const struct process *proc) { ON_NULL_RETURN_VAL(proc, -1); return proc->pid; } const char *process_get_appid(struct process *proc) { ON_NULL_RETURN_VAL(proc, NULL); if (!proc->appid) { proc->appid = app_info_provider_find_app_id(proc->pid); } return proc->appid; } const char *process_get_exe(struct process *proc) { ON_NULL_RETURN_VAL(proc, NULL); if (!proc->exe) { if (procfs_read_process_exe(proc->pid, &proc->exe) != 0) return NULL; } return proc->exe; } void process_shutdown(struct process *proc) { if (!proc) return; free(proc->appid); free(proc->exe); memset(proc, 0x0, sizeof(struct process)); } void process_move(struct process *dst, struct process *src) { memcpy(dst, src, sizeof(struct process)); src->appid = NULL; src->exe = NULL; } int process_get_cpu_usage_percentage(struct process *proc, float *usage) { ON_NULL_RETURN_VAL(proc, -1); ON_NULL_RETURN_VAL(usage, -1); *usage = (float)proc->frame_ticks_used * proc->frame_time_inverted * timescale; return 0; } int process_get_memory_usage_percentage(struct process *proc, float *usage) { ON_NULL_RETURN_VAL(proc, -1); ON_NULL_RETURN_VAL(usage, -1); *usage = (float)proc->memory_used / sys.total_memory; return 0; } int process_init() { if (sys_stats_update(&sys) != 0) { ERR("stats_update_system_stats failed."); return -1; } timescale = 1.0f / (float)sysconf(_SC_CLK_TCK); pagesize = getpagesize(); return 0; } void process_serialize(struct process *proc, JsonBuilder *builder) { ON_NULL_RETURN(proc); float tmp; json_builder_begin_object(builder); json_builder_set_member_name(builder, SCHEMA_RESULT_APP_ID); json_builder_add_string_value(builder, process_get_appid(proc)); json_builder_set_member_name(builder, SCHEMA_RESULT_EXE); json_builder_add_string_value(builder, process_get_exe(proc)); json_builder_set_member_name(builder, SCHEMA_RESULT_PID); json_builder_add_int_value(builder, process_get_pid(proc)); json_builder_set_member_name(builder, SCHEMA_RESULT_CPU); process_get_cpu_usage_percentage(proc, &tmp); json_builder_add_double_value(builder, tmp); json_builder_set_member_name(builder, SCHEMA_RESULT_MEMORY); process_get_memory_usage_percentage(proc, &tmp); json_builder_add_double_value(builder, tmp); json_builder_end_object(builder); }