From 63fc1facfdcc5c0a3ac723cd3d3142bc307611f6 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 28 Feb 2022 12:46:25 +0900 Subject: [PATCH 01/16] resource: Distinguish signed/unsigned and 32/64 bits integer data types To provide clients with the precise integer values, now support the new data types: - DATA_TYPE_INT(32-bit signed integer), - DATA_TPYE_INT64(64-bit signed integer), - DATA_TYPE_UINT(32-bit unsigned integer), - DATA_TPYE_UINT64(64-bit unsigned integer), Change-Id: I8f70fb38a1fd9876b53d52c2f7592120fc0f9b5c Signed-off-by: Dongwoo Lee --- include/util/resource.h | 8 +++++++- src/util/resource.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/include/util/resource.h b/include/util/resource.h index 00da7f5..a2d3765 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -27,6 +27,9 @@ enum monitor_data_type { DATA_TYPE_UNKNOWN = 0, DATA_TYPE_INT, + DATA_TYPE_INT64, + DATA_TYPE_UINT, + DATA_TYPE_UINT64, DATA_TYPE_DOUBLE, DATA_TYPE_STRING, DATA_TYPE_ARRAY, @@ -142,7 +145,10 @@ const struct resource_attribute *get_resource_attr(struct resource *resource, u_ struct resource_attribute_value * get_resource_attr_value(struct resource *resource, u_int64_t attr_id); -int get_resource_attr_integer(struct resource *resource, u_int64_t attr_id, int *data); +int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data); +int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_t *data); +int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32_t *data); +int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int32_t *data); int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double *data); int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char **data); int put_resource_attr_string(struct resource *resource, u_int64_t attr_id); diff --git a/src/util/resource.c b/src/util/resource.c index fedcb71..fc342f4 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -296,7 +296,7 @@ static bool check_attr_validate(struct resource *resource, u_int64_t attr_id, in return true; } -int get_resource_attr_integer(struct resource *resource, u_int64_t attr_id, int *data) +int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data) { struct resource_attribute_value *attr_value = NULL; @@ -307,7 +307,55 @@ int get_resource_attr_integer(struct resource *resource, u_int64_t attr_id, int if (!attr_value) return -EINVAL; - *data = (int)(intptr_t)attr_value->data; + *data = (int32_t)(intptr_t)attr_value->data; + + return 0; +} + +int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_t *data) +{ + struct resource_attribute_value *attr_value = NULL; + + if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT)) + return -EINVAL; + + attr_value = get_resource_attr_value(resource, attr_id); + if (!attr_value) + return -EINVAL; + + *data = (int64_t)(intptr_t)attr_value->data; + + return 0; +} + +int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32_t *data) +{ + struct resource_attribute_value *attr_value = NULL; + + if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT)) + return -EINVAL; + + attr_value = get_resource_attr_value(resource, attr_id); + if (!attr_value) + return -EINVAL; + + *data = (u_int32_t)(intptr_t)attr_value->data; + + return 0; +} + +int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int32_t *data) +{ + struct resource_attribute_value *attr_value = NULL; + + if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT)) + return -EINVAL; + + attr_value = get_resource_attr_value(resource, attr_id); + if (!attr_value) + return -EINVAL; + + *data = (u_int64_t)(intptr_t)attr_value->data; return 0; } -- 2.7.4 From f04876dfced39bf68e11ae0b04fef85da3a652dc Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 28 Feb 2022 14:29:14 +0900 Subject: [PATCH 02/16] util: kernel: Use 64-bit unsigned integer for memory information Since memory information node of kernel can be presented with 32-bit signed variable as maximum 2GB, to overcome this limitation, this changes related functions using 64-bit unsigned integer variable. Change-Id: Id1b1da468ca5e7c98cd65318c854cd5a98ae2086 Signed-off-by: Dongwoo Lee --- include/util/kernel.h | 4 ++-- src/resource/resource-memory.c | 46 ++++++++++++++++++++++++++--------------- src/resource/resource-process.c | 8 +++++-- src/util/kernel.c | 27 ++++++++++++++++-------- 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/include/util/kernel.h b/include/util/kernel.h index 4596ff6..f268e93 100644 --- a/include/util/kernel.h +++ b/include/util/kernel.h @@ -41,6 +41,6 @@ int kernel_get_total_cpu_stat(struct cpu_stat *total); int kernel_get_per_cpu_stat(struct cpu_stat *cpus, int num_possible_cpus, int *num_online_cpus); -int kernel_get_memory_info(const char *key); -int kernel_get_memory_total(void); +int kernel_get_memory_info(const char *key, u_int64_t *val); +int kernel_get_memory_total(u_int64_t *val); #endif diff --git a/src/resource/resource-memory.c b/src/resource/resource-memory.c index 63b8c08..f376feb 100644 --- a/src/resource/resource-memory.c +++ b/src/resource/resource-memory.c @@ -36,30 +36,40 @@ #define PROC_MEM_INFO_MEM_AVAILABLE "MemAvailable" #define PROC_MEM_INFO_MEM_FREE "MemFree" -static inline int memory_read_val_from_proc_node(uint32_t val_id) +static inline int memory_read_val_from_proc_node(uint32_t val_id, u_int64_t *val) { + int ret; + switch (val_id) { case MEMORY_TOTAL: - return kernel_get_memory_total(); + ret = kernel_get_memory_total(val); + break; case MEMORY_AVAILABLE: - return kernel_get_memory_info(PROC_MEM_INFO_MEM_AVAILABLE); + ret = kernel_get_memory_info(PROC_MEM_INFO_MEM_AVAILABLE, val); + break; case MEMORY_FREE: - return kernel_get_memory_info(PROC_MEM_INFO_MEM_FREE); + ret = kernel_get_memory_info(PROC_MEM_INFO_MEM_FREE, val); + break; + default: + _E("wrong memory resource attribute\n"); + ret = -EINVAL; } - return -EINVAL; + + return ret; } static int memory_get_total_memory(const struct resource *res, const struct resource_attribute *attr, void **data) { - int val; + u_int64_t val; + int ret; if (!res || !attr || !data) return -EINVAL; - val = memory_read_val_from_proc_node(attr->id); - if (val < 0) + ret = memory_read_val_from_proc_node(attr->id, &val); + if (ret < 0) return -EINVAL; *data = (void *)(intptr_t)val; @@ -71,13 +81,14 @@ static int memory_get_available_memory(const struct resource *res, const struct resource_attribute *attr, void **data) { - int val; + u_int64_t val; + int ret; if (!res || !attr || !data) return -EINVAL; - val = memory_read_val_from_proc_node(attr->id); - if (val < 0) + ret = memory_read_val_from_proc_node(attr->id, &val); + if (ret < 0) return -EINVAL; *data = (void *)(intptr_t)val; @@ -89,13 +100,14 @@ static int memory_get_free_memory(const struct resource *res, const struct resource_attribute *attr, void **data) { - int val; + u_int64_t val; + int ret; if (!res || !attr || !data) return -EINVAL; - val = memory_read_val_from_proc_node(attr->id); - if (val < 0) + ret = memory_read_val_from_proc_node(attr->id, &val); + if (ret < 0) return -EINVAL; *data = (void *)(intptr_t)val; @@ -107,21 +119,21 @@ static const struct resource_attribute memory_attrs[] = { { .name = "MEMORY_TOTAL", .id = MEMORY_TOTAL, - .type = DATA_TYPE_INT, + .type = DATA_TYPE_UINT64, .ops = { .get = memory_get_total_memory, }, }, { .name = "MEMORY_AVAILABLE", .id = MEMORY_AVAILABLE, - .type = DATA_TYPE_INT, + .type = DATA_TYPE_UINT64, .ops = { .get = memory_get_available_memory, }, }, { .name = "MEMORY_FREE", .id = MEMORY_FREE, - .type = DATA_TYPE_INT, + .type = DATA_TYPE_UINT64, .ops = { .get = memory_get_free_memory, } diff --git a/src/resource/resource-process.c b/src/resource/resource-process.c index 2eb3cf9..4defc09 100644 --- a/src/resource/resource-process.c +++ b/src/resource/resource-process.c @@ -467,6 +467,12 @@ static int process_init(struct resource *res) ctx->prev_total_time = get_total_cpu_time(); ctx->pid = (pid_t)(intptr_t)res->user_data; + ret = kernel_get_memory_total(&ctx->total_memory); + if (ret < 0) { + free(ctx); + return -EINVAL; + } + /* update initial status */ ret = update_taskstats(ctx); if (ret < 0) { @@ -481,8 +487,6 @@ static int process_init(struct resource *res) } memcpy(ctx->comm, stats.ac_comm, TS_COMM_LEN); - ctx->total_memory = kernel_get_memory_total() * 1024ULL; - res->priv = ctx; return 0; diff --git a/src/util/kernel.c b/src/util/kernel.c index a23c40e..a68e05b 100644 --- a/src/util/kernel.c +++ b/src/util/kernel.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -170,11 +171,9 @@ err: return ret; } -int kernel_get_memory_info(const char *key) +int kernel_get_memory_info(const char *key, u_int64_t *val) { - int ret = -EINVAL; char buf[BUFF_MAX]; - char str[BUFF_MAX]; FILE *fp = NULL; fp = fopen("/proc/meminfo", "r"); @@ -183,21 +182,31 @@ int kernel_get_memory_info(const char *key) while (fgets(buf, BUFF_MAX, fp)) { if (!strncmp(buf, key, strlen(key))) { - sscanf(buf, "%s %d", str, &ret); + sscanf(buf, "%*s %"PRIu64, val); + if (strstr(buf, "kB")) + *val *= 1024; break; } } fclose(fp); - return ret; + return 0; } -int kernel_get_memory_total(void) +int kernel_get_memory_total(u_int64_t *val) { static u_int64_t mem_total = 0; + int ret; - if (!mem_total) - mem_total = kernel_get_memory_info("MemTotal"); + if (!mem_total) { + ret = kernel_get_memory_info("MemTotal", &mem_total); + if (ret < 0) { + _E("failed to get system total memory\n"); + return -EINVAL; + } + } + + *val = mem_total; - return mem_total; + return 0; } -- 2.7.4 From 0b850329ce67e3059557625343824e64d8648b6c Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 28 Feb 2022 18:02:10 +0900 Subject: [PATCH 03/16] util: thread: Support free function for destorying queue Since lock-free queue can have various data type, users can pass free function when creating queue along with the corresponding data type in queue. Change-Id: I4ede38bd6e36a1622bb39c7183829c5372e3264b Signed-off-by: Dongwoo Lee --- include/util/queue.h | 3 ++- src/monitor/monitor-thread.c | 2 +- src/util/queue.c | 11 +++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/util/queue.h b/include/util/queue.h index 23b8331..2fdae3b 100644 --- a/include/util/queue.h +++ b/include/util/queue.h @@ -44,6 +44,7 @@ struct queue_node { struct queue { struct queue_node *head; struct queue_node *tail; + void (*free_func)(void *data); }; static inline void cpu_relax(void) @@ -53,7 +54,7 @@ static inline void cpu_relax(void) int enqueue(struct queue *queue, void *data); int dequeue(struct queue *queue, void **data); -int create_queue(struct queue **queue); +int create_queue(struct queue **queue, void (*free_func)(void *data)); void destroy_queue(struct queue *queue); #endif diff --git a/src/monitor/monitor-thread.c b/src/monitor/monitor-thread.c index e8a3b12..8cd535a 100644 --- a/src/monitor/monitor-thread.c +++ b/src/monitor/monitor-thread.c @@ -54,7 +54,7 @@ int monitor_thread_init(struct monitor *monitor) struct queue *queue; int ret; - ret = create_queue(&queue); + ret = create_queue(&queue, free); if (ret < 0) { _E("failed to create command queue\n"); return ret; diff --git a/src/util/queue.c b/src/util/queue.c index ec3819d..1312a2c 100644 --- a/src/util/queue.c +++ b/src/util/queue.c @@ -65,7 +65,7 @@ int dequeue(struct queue *queue, void **data) return 0; } -int create_queue(struct queue **queue) +int create_queue(struct queue **queue, void (*free_func)(void *data)) { struct queue *new_queue; struct queue_node *sentinel; @@ -80,6 +80,7 @@ int create_queue(struct queue **queue) return -ENOMEM; } + new_queue->free_func = free_func; new_queue->head = new_queue->tail = sentinel; new_queue->head->data = NULL; new_queue->head->next = NULL; @@ -91,7 +92,13 @@ int create_queue(struct queue **queue) void destroy_queue(struct queue *queue) { - do { } while (!dequeue(queue, NULL)); + void *data; + + if (queue->free_func) + while (!dequeue(queue, &data)) + queue->free_func(data); + else + do { } while (!dequeue(queue, NULL)); /* freeing remaining sentinel */ free(queue->head); -- 2.7.4 From 1eb3e815b9d4165c92cd6a54814fcaa2e7ef5622 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 24 Feb 2022 20:40:11 +0900 Subject: [PATCH 04/16] resource: Rework resource creation and initialization Change-Id: I386e277a20418b4030d3d5a63dcf10ea15898c6c Signed-off-by: Dongwoo Lee --- include/util/resource.h | 32 +++++++-- lib/tmonitor/tmonitor.h | 10 +++ src/resource/resource-battery.c | 1 - src/resource/resource-bus.c | 151 ++++++++++++++++++++++++++++++++++++---- src/resource/resource-cpu.c | 151 ++++++++++++++++++++++++++++++++++++---- src/resource/resource-display.c | 67 ++++++++++++++++-- src/resource/resource-gpu.c | 151 ++++++++++++++++++++++++++++++++++++---- src/resource/resource-memory.c | 1 - src/resource/resource-process.c | 106 ++++++++++++++++++++++------ src/resource/resource-system.c | 22 ++---- src/util/resource.c | 52 ++++++++------ 11 files changed, 636 insertions(+), 108 deletions(-) diff --git a/include/util/resource.h b/include/util/resource.h index a2d3765..a5057ec 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -68,6 +68,23 @@ struct resource_attribute { const struct resource_attribute_ops ops; }; +struct resource_control; + +struct resource_control_ops { + const int (*set)(const struct resource *res, + const struct resource_control *ctrl, + const void *data); + const int (*get)(const struct resource *res, + const struct resource_control *ctrl, + void **data); +}; + +struct resource_control { + const char name[BUFF_MAX]; + const u_int64_t id; + const struct resource_control_ops ops; +}; + struct resource_driver_ops { int (*init)(struct resource *res); void (*exit)(struct resource *res); @@ -78,15 +95,13 @@ struct resource_driver_ops { int (*prepare_update)(struct resource *res); }; -/* resource driver flags */ -#define RESOURCE_DRIVER_NO_DEVICE BIT32(1) - struct resource_driver { const char *name; const int type; - const int flags; const int num_attrs; const struct resource_attribute *attrs; + const int num_ctrls; + const struct resource_control *ctrls; const struct resource_driver_ops ops; }; @@ -105,13 +120,13 @@ struct resource { char *name; const struct resource_driver *driver; int type; - int index; - void *user_data; void *priv; int num_attrs; const struct resource_attribute *attrs; struct resource_attribute_value *attrs_value; + int num_ctrls; + const struct resource_control *ctrls; u_int64_t attr_interest; }; @@ -136,9 +151,12 @@ int add_resource_device(struct resource_device *resource_device); void remove_resource_device(struct resource_device *resource_device); /* Create/delete resource instance */ -struct resource *create_resource(int resource_type, int resource_index, void *user_data); +struct resource *create_resource(int resource_type); void delete_resource(struct resource *resource); +/* Handle resource control */ +int set_resource_control(struct resource *resource, u_int64_t ctrl_id, const void *data); + /* Handle resource attribute */ int update_resource_attrs(struct resource *resource); const struct resource_attribute *get_resource_attr(struct resource *resource, u_int64_t attr_id); diff --git a/lib/tmonitor/tmonitor.h b/lib/tmonitor/tmonitor.h index 5bc637c..3c4a667 100644 --- a/lib/tmonitor/tmonitor.h +++ b/lib/tmonitor/tmonitor.h @@ -51,6 +51,8 @@ extern "C" { #define CPU_ONLINE_CPU BIT(6) #define CPU_TEMPERATURE BIT(7) +#define CPU_CTRL_CLUSTER_ID BIT(0) + #define BUS_CUR_FREQ BIT(0) #define BUS_MIN_FREQ BIT(1) #define BUS_MAX_FREQ BIT(2) @@ -58,6 +60,8 @@ extern "C" { #define BUS_AVAILABLE_MAX_FREQ BIT(4) #define BUS_CUR_GOVERNOR BIT(5) +#define BUS_CTRL_DEVICE_ID BIT(0) + #define GPU_CUR_FREQ BIT(0) #define GPU_MIN_FREQ BIT(1) #define GPU_MAX_FREQ BIT(2) @@ -66,6 +70,8 @@ extern "C" { #define GPU_CUR_GOVERNOR BIT(5) #define GPU_TEMPERATURE BIT(6) +#define GPU_CTRL_DEVICE_ID BIT(0) + #define MEMORY_TOTAL BIT(0) #define MEMORY_AVAILABLE BIT(1) #define MEMORY_FREE BIT(2) @@ -81,6 +87,8 @@ extern "C" { #define DISPLAY_FPS BIT(0) +#define DISPLAY_CTRL_DEVICE_ID BIT(0) + #define SYSTEM_CPU_UTIL BIT(0) #define SYSTEM_CPU_USER_UTIL BIT(1) #define SYSTEM_CPU_SYS_UTIL BIT(2) @@ -98,6 +106,8 @@ extern "C" { #define PROCESS_DISK_WRITE BIT(5) #define PROCESS_COMM BIT(6) +#define PROCESS_CTRL_TGID BIT(0) + /** * @brief Initialize the tizen monitor * @param[in] Timer period (unit: millisecond, minimum value is 100ms) diff --git a/src/resource/resource-battery.c b/src/resource/resource-battery.c index 0e2364c..d621c37 100644 --- a/src/resource/resource-battery.c +++ b/src/resource/resource-battery.c @@ -151,6 +151,5 @@ static const struct resource_driver battery_resource_driver = { .type = RESOURCE_TYPE_BATTERY, .attrs = battery_attrs, .num_attrs = ARRAY_SIZE(battery_attrs), - .flags = RESOURCE_DRIVER_NO_DEVICE, }; RESOURCE_DRIVER_REGISTER(&battery_resource_driver) diff --git a/src/resource/resource-bus.c b/src/resource/resource-bus.c index f76f047..9ca48d9 100644 --- a/src/resource/resource-bus.c +++ b/src/resource/resource-bus.c @@ -32,16 +32,29 @@ #include +struct bus_context { + char *device_name; + int index; +}; + static int bus_get_cur_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct bus_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) return -EINVAL; - val = hal_power_dvfs_get_curr_freq(res->type, res->name); + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); + return -EINVAL; + } + + val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -54,12 +67,20 @@ static int bus_get_min_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct bus_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) return -EINVAL; - val = hal_power_dvfs_get_min_freq(res->type, res->name); + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); + return -EINVAL; + } + + val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -72,12 +93,20 @@ static int bus_get_max_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct bus_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_max_freq(res->type, res->name); + val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -90,12 +119,20 @@ static int bus_get_available_min_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct bus_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_available_min_freq(res->type, res->name); + val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -108,12 +145,20 @@ static int bus_get_available_max_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct bus_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_available_max_freq(res->type, res->name); + val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -126,13 +171,21 @@ static int bus_get_curr_governor(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct bus_context *ctx; char buf[BUFF_MAX]; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_curr_governor(res->type, res->name, buf); + val = hal_power_dvfs_get_curr_governor(res->type, ctx->device_name, buf); if (val < 0) return -EINVAL; @@ -189,10 +242,84 @@ static const struct resource_attribute bus_attrs[] = { }, }; +static int bus_setup_device_id(const struct resource *res, + const struct resource_control *ctrl, + const void *data) +{ + struct bus_context *ctx; + const struct resource_device *device; + int device_id = (int)(intptr_t)data; + + if (!res || !res->priv || !ctrl) + return -EINVAL; + + device = find_resource_device(res->type, device_id); + if (!device) { + _E("Not available resource: type: %s, index: %d\n", + res->name, device_id); + return -EINVAL; + } + + ctx = res->priv; + + if (ctx->device_name) + free(ctx->device_name); + + ctx->device_name = g_strdup(device->name); + ctx->index = device_id; + + return 0; +} + +static const struct resource_control bus_ctrls[] = { + { + .name = "BUS_CTRL_DEVICE_ID", + .id = BUS_CTRL_DEVICE_ID, + .ops = { + .set = bus_setup_device_id, + }, + }, +}; + +static int bus_init(struct resource *res) +{ + struct bus_context *ctx; + + ctx = calloc(1, sizeof(struct bus_context)); + if (!ctx) + return -ENOMEM; + + res->priv = ctx; + + return 0; +} + +static void bus_exit(struct resource *res) +{ + struct bus_context *ctx; + + if (res && res->priv) { + ctx = res->priv; + if (ctx->device_name) { + free(ctx->device_name); + ctx->device_name = NULL; + } + free(ctx); + res->priv = NULL; + } +} + static const struct resource_driver bus_resource_driver = { .name = "Memory Bus", .type = RESOURCE_TYPE_BUS, .attrs = bus_attrs, .num_attrs = ARRAY_SIZE(bus_attrs), + .ctrls = bus_ctrls, + .num_ctrls = ARRAY_SIZE(bus_ctrls), + .ops = { + .init = bus_init, + .exit = bus_exit, + }, }; RESOURCE_DRIVER_REGISTER(&bus_resource_driver) + diff --git a/src/resource/resource-cpu.c b/src/resource/resource-cpu.c index 8d288f4..9930016 100644 --- a/src/resource/resource-cpu.c +++ b/src/resource/resource-cpu.c @@ -32,16 +32,29 @@ #include +struct cpu_context { + char *device_name; + int index; +}; + static int cpu_get_cur_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct cpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) return -EINVAL; - val = hal_power_dvfs_get_curr_freq(res->type, res->name); + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); + return -EINVAL; + } + + val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -54,12 +67,20 @@ static int cpu_get_min_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct cpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) return -EINVAL; - val = hal_power_dvfs_get_min_freq(res->type, res->name); + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); + return -EINVAL; + } + + val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -72,12 +93,20 @@ static int cpu_get_max_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct cpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_max_freq(res->type, res->name); + val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -90,12 +119,20 @@ static int cpu_get_available_min_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct cpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_available_min_freq(res->type, res->name); + val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -108,12 +145,20 @@ static int cpu_get_available_max_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct cpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_available_max_freq(res->type, res->name); + val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -126,13 +171,21 @@ static int cpu_get_curr_governor(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct cpu_context *ctx; char buf[BUFF_MAX]; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_curr_governor(res->type, res->name, buf); + val = hal_power_dvfs_get_curr_governor(res->type, ctx->device_name, buf); if (val < 0) return -EINVAL; @@ -217,10 +270,84 @@ static const struct resource_attribute cpu_attrs[] = { }, }; +static int cpu_setup_cluster_id(const struct resource *res, + const struct resource_control *ctrl, + const void *data) +{ + struct cpu_context *ctx; + const struct resource_device *device; + int resource_index = (int)(intptr_t)data; + + if (!res || !res->priv || !ctrl) + return -EINVAL; + + device = find_resource_device(res->type, resource_index); + if (!device) { + _E("Not available resource: type: %s, index: %d\n", + res->name, resource_index); + return -EINVAL; + } + + ctx = res->priv; + + if (ctx->device_name) + free(ctx->device_name); + + ctx->device_name = g_strdup(device->name); + ctx->index = resource_index; + + return 0; +} + +static const struct resource_control cpu_ctrls[] = { + { + .name = "CPU_CTRL_CLUSTER_ID", + .id = CPU_CTRL_CLUSTER_ID, + .ops = { + .set = cpu_setup_cluster_id, + }, + }, +}; + +static int cpu_init(struct resource *res) +{ + struct cpu_context *ctx; + + ctx = calloc(1, sizeof(struct cpu_context)); + if (!ctx) + return -ENOMEM; + + res->priv = ctx; + + return 0; +} + +static void cpu_exit(struct resource *res) +{ + struct cpu_context *ctx; + + if (res && res->priv) { + ctx = res->priv; + if (ctx->device_name) { + free(ctx->device_name); + ctx->device_name = NULL; + } + free(ctx); + res->priv = NULL; + } +} + static const struct resource_driver cpu_resource_driver = { .name = "CPU", .type = RESOURCE_TYPE_CPU, .attrs = cpu_attrs, .num_attrs = ARRAY_SIZE(cpu_attrs), + .ctrls = cpu_ctrls, + .num_ctrls = ARRAY_SIZE(cpu_ctrls), + .ops = { + .init = cpu_init, + .exit = cpu_exit, + }, }; RESOURCE_DRIVER_REGISTER(&cpu_resource_driver) + diff --git a/src/resource/resource-display.c b/src/resource/resource-display.c index 7210af2..f3b7af9 100644 --- a/src/resource/resource-display.c +++ b/src/resource/resource-display.c @@ -55,11 +55,19 @@ static int display_get_fps(const struct resource *res, GVariant *result, *value; GError *err = NULL; struct display_fps_data fps_data; + int *disp_id; int ret = 0; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) return -EINVAL; + disp_id = res->priv; + + if (*disp_id < 0) { + _E("%s: DISPLAY_CTRL_DEVICE_ID is not yet initialized\n", res->name); + return -EINVAL; + } + /* Connect dbus interface and receive message */ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); if (err) { @@ -92,13 +100,13 @@ static int display_get_fps(const struct resource *res, /* Parse the received data */ result = g_variant_get_child_value(g_dbus_message_get_body(reply), 0); - if (g_variant_n_children(result) <= res->index) { + if (g_variant_n_children(result) == 0) { fps_data.fps = 0.0; goto out; } /* Get the fps information according to the index of resource_device */ - value = g_variant_get_child_value(result, res->index); + value = g_variant_get_child_value(result, *disp_id); g_variant_get(value, "(usiud)", &fps_data.type, fps_data.output, &fps_data.zpos, &fps_data.window, &fps_data.fps); @@ -127,11 +135,62 @@ static const struct resource_attribute display_attrs[] = { }, }; +static int display_setup_device_id(const struct resource *res, + const struct resource_control *ctrl, + const void *data) +{ + int *disp_id; + + if (!res || !res->priv || !ctrl) + return -EINVAL; + + disp_id = res->priv; + + *disp_id = (int)(intptr_t)data; + + return 0; +} + +static const struct resource_control display_ctrls[] = { + { + .name = "DISPLAY_CTRL_DEVICE_ID", + .id = DISPLAY_CTRL_DEVICE_ID, + .ops = { + .set = display_setup_device_id, + }, + }, +}; + +static int display_init(struct resource *res) +{ + int *disp_id; + + disp_id = malloc(sizeof(int)); + if (!disp_id) + return -ENOMEM; + + *disp_id = -1; + + res->priv = disp_id; + + return 0; +} + +static void display_exit(struct resource *res) +{ + if (res && res->priv) + free(res->priv); +} static const struct resource_driver display_resource_driver = { .name = "DISPLAY", .type = RESOURCE_TYPE_DISPLAY, .attrs = display_attrs, .num_attrs = ARRAY_SIZE(display_attrs), - .flags = RESOURCE_DRIVER_NO_DEVICE, + .ctrls = display_ctrls, + .num_ctrls = ARRAY_SIZE(display_ctrls), + .ops = { + .init = display_init, + .exit = display_exit, + }, }; RESOURCE_DRIVER_REGISTER(&display_resource_driver) diff --git a/src/resource/resource-gpu.c b/src/resource/resource-gpu.c index e7afa19..1c27599 100644 --- a/src/resource/resource-gpu.c +++ b/src/resource/resource-gpu.c @@ -32,16 +32,29 @@ #include +struct gpu_context { + char *device_name; + int index; +}; + static int gpu_get_cur_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct gpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) return -EINVAL; - val = hal_power_dvfs_get_curr_freq(res->type, res->name); + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); + return -EINVAL; + } + + val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -54,12 +67,20 @@ static int gpu_get_min_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct gpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) return -EINVAL; - val = hal_power_dvfs_get_min_freq(res->type, res->name); + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); + return -EINVAL; + } + + val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -72,12 +93,20 @@ static int gpu_get_max_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct gpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_max_freq(res->type, res->name); + val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -90,12 +119,20 @@ static int gpu_get_available_min_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct gpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_available_min_freq(res->type, res->name); + val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -108,12 +145,20 @@ static int gpu_get_available_max_freq(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct gpu_context *ctx; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_available_max_freq(res->type, res->name); + val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); if (val < 0) return -EINVAL; @@ -126,13 +171,21 @@ static int gpu_get_curr_governor(const struct resource *res, const struct resource_attribute *attr, void **data) { + struct gpu_context *ctx; char buf[BUFF_MAX]; int val; - if (!res || !attr || !data) + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->device_name) { + _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); return -EINVAL; + } - val = hal_power_dvfs_get_curr_governor(res->type, res->name, buf); + val = hal_power_dvfs_get_curr_governor(res->type, ctx->device_name, buf); if (val < 0) return -EINVAL; @@ -203,10 +256,84 @@ static const struct resource_attribute gpu_attrs[] = { }, }; +static int gpu_setup_device_id(const struct resource *res, + const struct resource_control *ctrl, + const void *data) +{ + struct gpu_context *ctx; + const struct resource_device *device; + int resource_index = (int)(intptr_t)data; + + if (!res || !res->priv || !ctrl) + return -EINVAL; + + device = find_resource_device(res->type, resource_index); + if (!device) { + _E("Not available resource: type: %s, index: %d\n", + res->name, resource_index); + return -EINVAL; + } + + ctx = res->priv; + + if (ctx->device_name) + free(ctx->device_name); + + ctx->device_name = g_strdup(device->name); + ctx->index = resource_index; + + return 0; +} + +static const struct resource_control gpu_ctrls[] = { + { + .name = "GPU_CTRL_DEVICE_ID", + .id = GPU_CTRL_DEVICE_ID, + .ops = { + .set = gpu_setup_device_id, + }, + }, +}; + +static int gpu_init(struct resource *res) +{ + struct gpu_context *ctx; + + ctx = calloc(1, sizeof(struct gpu_context)); + if (!ctx) + return -ENOMEM; + + res->priv = ctx; + + return 0; +} + +static void gpu_exit(struct resource *res) +{ + struct gpu_context *ctx; + + if (res && res->priv) { + ctx = res->priv; + if (ctx->device_name) { + free(ctx->device_name); + ctx->device_name = NULL; + } + free(ctx); + res->priv = NULL; + } +} + static const struct resource_driver gpu_resource_driver = { .name = "GPU", .type = RESOURCE_TYPE_GPU, .attrs = gpu_attrs, .num_attrs = ARRAY_SIZE(gpu_attrs), + .ctrls = gpu_ctrls, + .num_ctrls = ARRAY_SIZE(gpu_ctrls), + .ops = { + .init = gpu_init, + .exit = gpu_exit, + }, }; RESOURCE_DRIVER_REGISTER(&gpu_resource_driver) + diff --git a/src/resource/resource-memory.c b/src/resource/resource-memory.c index f376feb..74c8fd4 100644 --- a/src/resource/resource-memory.c +++ b/src/resource/resource-memory.c @@ -145,6 +145,5 @@ static const struct resource_driver memory_resource_driver = { .type = RESOURCE_TYPE_MEMORY, .attrs = memory_attrs, .num_attrs = ARRAY_SIZE(memory_attrs), - .flags = RESOURCE_DRIVER_NO_DEVICE, }; RESOURCE_DRIVER_REGISTER(&memory_resource_driver) diff --git a/src/resource/resource-process.c b/src/resource/resource-process.c index 4defc09..1c28294 100644 --- a/src/resource/resource-process.c +++ b/src/resource/resource-process.c @@ -29,7 +29,7 @@ #include struct process_context { - pid_t pid; + pid_t tgid; char comm[TS_COMM_LEN]; struct taskstats prev; struct taskstats curr; @@ -54,6 +54,12 @@ static int process_get_cpu_util(const struct resource *res, return -EINVAL; ctx = res->priv; + + if (!ctx->tgid) { + _E("resource %s is not yet initialized\n", res->name); + return -EINVAL; + } + prev = &ctx->prev; curr = &ctx->curr; @@ -87,6 +93,12 @@ static int process_get_mem_virt(const struct resource *res, return -EINVAL; ctx = res->priv; + + if (!ctx->tgid) { + _E("resource %s is not yet initialized\n", res->name); + return -EINVAL; + } + curr = &ctx->curr; virt = (double)curr->virtmem / (double)curr->ac_stime; @@ -109,6 +121,12 @@ static int process_get_mem_rss(const struct resource *res, return -EINVAL; ctx = res->priv; + + if (!ctx->tgid) { + _E("resource %s is not yet initialized\n", res->name); + return -EINVAL; + } + curr = &ctx->curr; rss = (double)curr->coremem / (double)curr->ac_stime; @@ -142,6 +160,12 @@ static int process_get_disk_read(const struct resource *res, return -EINVAL; ctx = res->priv; + + if (!ctx->tgid) { + _E("resource %s is not yet initialized\n", res->name); + return -EINVAL; + } + prev = &ctx->prev; curr = &ctx->curr; @@ -166,6 +190,12 @@ static int process_get_disk_write(const struct resource *res, return -EINVAL; ctx = res->priv; + + if (!ctx->tgid) { + _E("resource %s is not yet initialized\n", res->name); + return -EINVAL; + } + prev = &ctx->prev; curr = &ctx->curr; @@ -188,6 +218,12 @@ static int process_get_comm(const struct resource *res, return -EINVAL; ctx = res->priv; + + if (!ctx->tgid) { + _E("resource %s is not yet initialized\n", res->name); + return -EINVAL; + } + *data = g_strdup(ctx->comm); return 0; @@ -389,7 +425,7 @@ static int update_taskstats(struct process_context *ctx) memset(curr, 0, sizeof(struct taskstats)); - sprintf(task_dir_path, "/proc/%d/task/", ctx->pid); + sprintf(task_dir_path, "/proc/%d/task/", ctx->tgid); task_dir = opendir(task_dir_path); if (!task_dir) @@ -425,6 +461,51 @@ static int update_taskstats(struct process_context *ctx) return 0; } +static int process_setup_tgid(const struct resource *res, + const struct resource_control *ctrl, + const void *data) +{ + struct taskstats stats; + struct process_context *ctx; + u_int64_t total_memory; + int ret; + + if (!res || !res->priv || !ctrl) + return -EINVAL; + + ctx = res->priv; + + total_memory = ctx->total_memory; + memset(ctx, 0, sizeof(*ctx)); + + ctx->total_memory = total_memory; + ctx->tgid = (pid_t)(intptr_t)data; + ctx->prev_total_time = get_total_cpu_time(); + + /* update initial status */ + ret = update_taskstats(ctx); + if (ret < 0) + return -EINVAL; + + ret = query_taskstats(&stats, TASKSTATS_CMD_ATTR_PID, ctx->tgid); + if (ret < 0) + return -EINVAL; + + memcpy(ctx->comm, stats.ac_comm, TS_COMM_LEN); + + return 0; +} + +static const struct resource_control process_ctrls[] = { + { + .name = "PROCESS_CTRL_TGID", + .id = PROCESS_CTRL_TGID, + .ops = { + .set = process_setup_tgid, + }, + }, +}; + static int process_prepare_update(struct resource *res) { struct process_context *ctx = res->priv; @@ -449,7 +530,6 @@ static int process_prepare_update(struct resource *res) static int process_init(struct resource *res) { - struct taskstats stats; struct process_context *ctx; int ret; @@ -464,29 +544,12 @@ static int process_init(struct resource *res) if (!ctx) return -ENOMEM; - ctx->prev_total_time = get_total_cpu_time(); - ctx->pid = (pid_t)(intptr_t)res->user_data; - ret = kernel_get_memory_total(&ctx->total_memory); if (ret < 0) { free(ctx); return -EINVAL; } - /* update initial status */ - ret = update_taskstats(ctx); - if (ret < 0) { - free(ctx); - return -EINVAL; - } - - ret = query_taskstats(&stats, TASKSTATS_CMD_ATTR_PID, ctx->pid); - if (ret < 0) { - free(ctx); - return -EINVAL; - } - memcpy(ctx->comm, stats.ac_comm, TS_COMM_LEN); - res->priv = ctx; return 0; @@ -507,8 +570,9 @@ static const struct resource_driver process_resource_driver = { .name = "PROCESS", .type = RESOURCE_TYPE_PROCESS, .attrs = process_attrs, - .flags = RESOURCE_DRIVER_NO_DEVICE, .num_attrs = ARRAY_SIZE(process_attrs), + .ctrls = process_ctrls, + .num_ctrls = ARRAY_SIZE(process_ctrls), .ops = { .init = process_init, .exit = process_exit, diff --git a/src/resource/resource-system.c b/src/resource/resource-system.c index 2538ed0..e62b6d2 100644 --- a/src/resource/resource-system.c +++ b/src/resource/resource-system.c @@ -91,8 +91,7 @@ static int system_get_avg_cpu_util(const struct resource *res, util = __calculate_cpu_util(attr->id, &sysdata->prev_avg, &sysdata->curr_avg); if (util < 0) { - _W("failed to calculate average cpu util (%s.%d: %s)\n", - res->name, res->index, attr->name); + _W("failed to calculate average cpu util (%s: %s)\n", res->name, attr->name); util = 0; } *data = (void *)(intptr_t)util; @@ -132,8 +131,7 @@ static int system_get_per_cpu_util(const struct resource *res, &sysdata->prev_cpus[i], &sysdata->curr_cpus[i]); if (utils[i] < 0) { - _W("failed to calculate per-cpu util (%s.%d: %s)\n", - res->name, res->index, attr->name); + _W("failed to calculate per-cpu util (%s: %s)\n", res->name, attr->name); utils[i] = 0; } } @@ -238,8 +236,7 @@ static int system_driver_init(struct resource *res) ret = kernel_get_possible_cpu_num(); if (ret < 0) { - _I("failed to get possible cpu on system driver (%s.%d)\n", - res->name, res->index); + _I("failed to get possible cpu on system driver (%s)\n", res->name); goto err; } sysdata->num_possible_cpus = ret; @@ -247,8 +244,7 @@ static int system_driver_init(struct resource *res) sysdata->prev_cpus = calloc(sysdata->num_possible_cpus, sizeof(struct cpu_stat)); if (!sysdata->prev_cpus) { - _I("failed to allocate memory of prev_cpus (%s.%d)\n", - res->name, res->index); + _I("failed to allocate memory of prev_cpus (%s)\n", res->name); ret = -ENOMEM; goto err; } @@ -256,8 +252,7 @@ static int system_driver_init(struct resource *res) sysdata->curr_cpus = calloc(sysdata->num_possible_cpus, sizeof(struct cpu_stat)); if (!sysdata->curr_cpus) { - _I("failed to allocate memory of curr_cpus (%s.%d)\n", - res->name, res->index); + _I("failed to allocate memory of curr_cpus (%s)\n", res->name); ret = -ENOMEM; goto err_prev_cpus; } @@ -296,8 +291,7 @@ static int system_driver_prepare_update(struct resource *res) memcpy(&sysdata->prev_avg, &sysdata->curr_avg, sizeof(sysdata->prev_avg)); ret = kernel_get_total_cpu_stat(&sysdata->curr_avg); if (ret < 0) { - _I("failed to calculate average cpu util (%s:%d)\n", - res->name, res->index); + _I("failed to calculate average cpu util (%s)\n", res->name); return ret; } @@ -308,8 +302,7 @@ static int system_driver_prepare_update(struct resource *res) sysdata->num_possible_cpus, &sysdata->num_online_cpus); if (ret < 0) { - _I("failed to calculate per-cpu util (%s:%d)\n", - res->name, res->index); + _I("failed to calculate per-cpu util (%s)\n", res->name); return ret; } @@ -321,7 +314,6 @@ static const struct resource_driver system_resource_driver = { .type = RESOURCE_TYPE_SYSTEM, .attrs = system_attrs, .num_attrs = ARRAY_SIZE(system_attrs), - .flags = RESOURCE_DRIVER_NO_DEVICE, .ops = { .init = system_driver_init, .exit = system_driver_exit, diff --git a/src/util/resource.c b/src/util/resource.c index fc342f4..fd14ec4 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -24,7 +24,9 @@ #include #define RESOURCE_ATTR_MASK (ULLONG_MAX) -#define RESOURCE_ATTR_INDEX(id) (63 - __builtin_clzll(id)) +#define BIT64_INDEX(id) (63 - __builtin_clzll(id)) +#define RESOURCE_ATTR_INDEX(id) BIT64_INDEX(id) +#define RESOURCE_CTRL_INDEX(id) BIT64_INDEX(id) static GList *g_resource_driver_head; static GList *g_resource_device_head; @@ -153,10 +155,8 @@ void delete_resource(struct resource *resource) do_delete_resource(resource); } -struct resource *create_resource(int resource_type, int resource_index, - void *user_data) +struct resource *create_resource(int resource_type) { - const struct resource_device *device = NULL; const struct resource_driver *driver = NULL; struct resource *resource = NULL; int i, ret; @@ -165,30 +165,13 @@ struct resource *create_resource(int resource_type, int resource_index, if (!driver) return NULL; - if (!(driver->flags & RESOURCE_DRIVER_NO_DEVICE)) { - device = find_resource_device(resource_type, resource_index); - if (!device) { - _E("Not available resource: type: %d, index: %d\n", - resource_type, resource_index); - return NULL; - } - } - resource = calloc(1, sizeof(*resource)); if (!resource) return NULL; - if (device) { - resource->type = device->type; - resource->name = g_strdup(device->name); - resource->index = device->index; - } else { - resource->type = resource_type; - resource->name = g_strdup(driver->name); - resource->index = resource_index; - } + resource->type = resource_type; + resource->name = g_strdup(driver->name); resource->driver = driver; - resource->user_data = user_data; resource->num_attrs = driver->num_attrs; resource->attrs = driver->attrs; resource->attrs_value = calloc(resource->num_attrs, @@ -201,6 +184,9 @@ struct resource *create_resource(int resource_type, int resource_index, for (i = 0; i < resource->num_attrs; i++) resource->attrs_value[i].type = driver->attrs[i].type; + resource->ctrls = driver->ctrls; + resource->num_ctrls = driver->num_ctrls; + if (driver->ops.init) { ret = driver->ops.init(resource); if (ret < 0) { @@ -212,6 +198,26 @@ struct resource *create_resource(int resource_type, int resource_index, return resource; } +int set_resource_control(struct resource *resource, u_int64_t ctrl_id, const void *data) +{ + const struct resource_control *ctrl; + int ctrl_index = RESOURCE_CTRL_INDEX(ctrl_id); + int ret; + + if (!resource) + return -EINVAL; + + ctrl = &resource->ctrls[ctrl_index]; + if (!ctrl->ops.set) + return -ENOTSUP; + + ret = ctrl->ops.set(resource, ctrl, data); + if (ret < 0) + return ret; + + return 0; +} + static int update_resource_attr(struct resource *resource, u_int64_t attr_id) { int attr_index = RESOURCE_ATTR_INDEX(attr_id); -- 2.7.4 From 431ac4b1d61786ee073a75bb1c211cde792b1c02 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 3 Mar 2022 20:42:40 +0900 Subject: [PATCH 05/16] util: resource: Give unique id for each resource Change-Id: I9f4eb44862ed42a2189d1c1f6cac47e760b876fe Signed-off-by: Dongwoo Lee --- include/util/resource.h | 1 + src/util/resource.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/util/resource.h b/include/util/resource.h index a5057ec..a794e58 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -117,6 +117,7 @@ struct resource_device { }; struct resource { + int id; char *name; const struct resource_driver *driver; int type; diff --git a/src/util/resource.c b/src/util/resource.c index fd14ec4..8e16332 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -28,6 +28,7 @@ #define RESOURCE_ATTR_INDEX(id) BIT64_INDEX(id) #define RESOURCE_CTRL_INDEX(id) BIT64_INDEX(id) +static int g_resource_id; static GList *g_resource_driver_head; static GList *g_resource_device_head; @@ -169,6 +170,7 @@ struct resource *create_resource(int resource_type) if (!resource) return NULL; + resource->id = __sync_fetch_and_add(&g_resource_id, 1); resource->type = resource_type; resource->name = g_strdup(driver->name); resource->driver = driver; -- 2.7.4 From 0ee88546f91a2cea99daba4152d0dde7827b0eb6 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 7 Mar 2022 16:50:11 +0900 Subject: [PATCH 06/16] monitor: Add request-server and request-handler-thread To provide libpass API via socket, a manager is required to manage network connections and requests from clients. Request-server is a manager to manage network connections. It accepts and establishes a socket connection from each client, then spawns a per-client request-handler-thread to deal with incoming requests from the client if required. Change-Id: I17cdf1fde69022663c2369b55982ac43e5b5c688 Signed-off-by: Sung-hun Kim Signed-off-by: Chanwoo Choi Signed-off-by: Dongwoo Lee --- CMakeLists.txt | 2 + include/util/request-handler.h | 40 +++++ include/util/request.h | 40 +++++ src/monitor/request-handler.c | 347 +++++++++++++++++++++++++++++++++++++++++ src/monitor/request-server.c | 184 ++++++++++++++++++++++ 5 files changed, 613 insertions(+) create mode 100644 include/util/request-handler.h create mode 100644 include/util/request.h create mode 100644 src/monitor/request-handler.c create mode 100644 src/monitor/request-server.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a04a81..b100c63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,8 @@ SET(SRCS src/monitor/monitor.c src/monitor/monitor-thread.c src/monitor/monitor-command.c + src/monitor/request-server.c + src/monitor/request-handler.c ) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/include/util/request-handler.h b/include/util/request-handler.h new file mode 100644 index 0000000..87f8d0e --- /dev/null +++ b/include/util/request-handler.h @@ -0,0 +1,40 @@ +/* + * PASS (Power Aware System Service) + * + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +#ifndef __REQUEST_HANDLER_H__ +#define __REQUEST_HANDLER_H__ + +#include +#include + +#include + +extern const char *request_type_str[]; + +struct request_client { + int id; + int nr_resources; + struct thread *worker; + GHashTable *resource_table; + GMutex mutex; +}; + +#define REQUEST_BUFFER_MAX 1000 + +int create_request_client(int socket_fd); + +#endif /* __REQUEST_HANDLER_H__ */ diff --git a/include/util/request.h b/include/util/request.h new file mode 100644 index 0000000..47b30cf --- /dev/null +++ b/include/util/request.h @@ -0,0 +1,40 @@ +/* + * PASS (Power Aware System Service) + * + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +#ifndef __REQUEST_H__ +#define __REQUEST_H__ + +/* + * request format + * REQUEST_TYPE:REQUEST_CONTENT(if required) + */ + +enum { + REQUEST_CREATE_RESOURCE, + REQUEST_UPDATE_RESOURCE, + REQUEST_REMOVE_RESOURCE, + REQUEST_SET_ATTR_INTEREST, + REQUEST_UNSET_ATTR_INTEREST, + REQUEST_SET_RESOURCE_CONTROL, + REQUEST_GET_VALUE_INT, + REQUEST_GET_RESOURCE_NUM, + REQUEST_GET_AVAILABLE_ATTRS, + REQUEST_MAX, +}; + +#endif /* __REQUEST_H__ */ + diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c new file mode 100644 index 0000000..8082e81 --- /dev/null +++ b/src/monitor/request-handler.c @@ -0,0 +1,347 @@ +/* + * PASS (Power Aware System Service) + * + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/** + * @file request-handler-thread.c + * @brief TBD + * @ingroup TBD + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static void free_resource(gpointer key, gpointer value, gpointer user_data) +{ + struct resource *res = value; + + delete_resource(res); +} + +static void finalize_request_client(struct request_client *client) +{ + if (!client) + return; + + if (client->resource_table) { + g_mutex_lock(&client->mutex); + g_hash_table_foreach(client->resource_table, (GHFunc)free_resource, NULL); + g_mutex_unlock(&client->mutex); + } +} + +static void +register_resource_to_client(struct request_client *client, struct resource *res) +{ + g_mutex_lock(&client->mutex); + g_hash_table_insert(client->resource_table, (gpointer)&res->id, (gpointer)res); + g_mutex_unlock(&client->mutex); +} + +static struct resource * +get_resource_by_id(struct request_client *client, int resource_id) +{ + struct resource *res; + + g_mutex_lock(&client->mutex); + res = g_hash_table_lookup(client->resource_table, (gpointer)&resource_id); + g_mutex_unlock(&client->mutex); + + return res; +} + +static int handle_request_create_resource(struct request_client *client, char *args) +{ + struct resource *res; + int resource_type; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_CREATE_RESOURCE args: + * - + */ + resource_type = atoi(args); + + res = create_resource(resource_type); + if (!res) + return -EINVAL; + + register_resource_to_client(client, res); + + return res->id; +} + +static int handle_request_update_resource(struct request_client *client, char *args) +{ + struct resource *res; + int resource_id; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_UPDATE_RESOURCE args: + * - + */ + resource_id = atoi(args); + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + return update_resource_attrs(res); +} + +static int handle_request_set_attr_interest(struct request_client *client, char *args) +{ + struct resource *res; + int resource_id; + u_int64_t interest_masks; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_SET_ATTR_INTEREST args: + * - + */ + if (sscanf(args, "%d:%"PRIu64, &resource_id, &interest_masks) < 2) + return -EINVAL; + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + set_resource_attr_interest(res, interest_masks); + + return 0; +} + +static int handle_request_set_resource_control(struct request_client *client, char *args) +{ + struct resource *res; + int resource_id, value; + u_int64_t ctrl_id; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_SET_RESOURCE_CONTROL args: + * - + */ + if (sscanf(args, "%d:%"PRIu64":%d", &resource_id, &ctrl_id, &value) < 3) + return -EINVAL; + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + return set_resource_control(res, ctrl_id, (void *)(intptr_t)value); +} + +static int handle_request_get_value_int(struct request_client *client, char *args, int32_t *value) +{ + struct resource *res; + int resource_id; + u_int64_t attr_id; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_GET_VALUE_INT args: + * - + */ + if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + return -EINVAL; + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + return get_resource_attr_int(res, attr_id, value); +} + +static int split_request_type_and_args(char *buffer, char **args) +{ + char *request_type_str; + + request_type_str = strsep(&buffer, ":"); + + *args = buffer; + + return atoi(request_type_str); +} + +static void handle_request(struct request_client *client, char *buffer) +{ + char _response[REQUEST_BUFFER_MAX]; + char *response = _response; + char *args; + int request_type; + int ret, len; + + request_type = split_request_type_and_args(buffer, &args); + + /** + * Format of response + * - + */ + len = sprintf(response, "%d:", request_type); + response += len; + + switch (request_type) { + case REQUEST_CREATE_RESOURCE: + ret = handle_request_create_resource(client, args); + if (ret < 0) + _D("failed to create resource"); + break; + case REQUEST_UPDATE_RESOURCE: + ret = handle_request_update_resource(client, args); + if (ret < 0) + _D("failed to update resource"); + break; + case REQUEST_SET_ATTR_INTEREST: + ret = handle_request_set_attr_interest(client, args); + if (ret < 0) + _D("failed to set attr interest"); + break; + case REQUEST_SET_RESOURCE_CONTROL: + ret = handle_request_set_resource_control(client, args); + if (ret < 0) + _D("failed to set resource control"); + break; + case REQUEST_GET_VALUE_INT: + { + int32_t value; + + ret = handle_request_get_value_int(client, args, &value); + if (ret < 0) + _D("failed to get value"); + + len = sprintf(response, "%d:", value); + response += len; + } + break; + default: + _E("Invliad request type: %d", request_type); + ret = -EINVAL; + break; + } + sprintf(response, "%d", ret); + + if (send(client->id, _response, strlen(_response), 0) < 0) + _E("Failed to send respones, error: %s", strerror(errno)); +} + +static GList *g_request_client_head; +static GMutex g_server_lock; + +static void add_client_to_list(struct request_client *client) +{ + if (!client) + return; + + g_mutex_lock(&g_server_lock); + g_request_client_head = + g_list_append(g_request_client_head, (gpointer)client); + g_mutex_unlock(&g_server_lock); +} + +static void remove_client_from_list(struct request_client *client) +{ + if (!client) + return; + + g_mutex_lock(&g_server_lock); + g_request_client_head = + g_list_remove(g_request_client_head, (gpointer)client); + g_mutex_unlock(&g_server_lock); +} + +static void destroy_request_client(struct request_client *client) +{ + remove_client_from_list(client); + free(client); +} + +static int request_handler_func(void *data, void **result) +{ + char buffer[REQUEST_BUFFER_MAX + 1]; + struct request_client *client = (struct request_client *)data; + int len; + + _D("Start worker thread for client-%d", client->id); + + while (1) { + len = recv(client->id, buffer, REQUEST_BUFFER_MAX, 0); + if (len == 0) { + _D("Client-%d is disconnected", client->id); + finalize_request_client(client); + close(client->id); + destroy_request_client(client); + return THREAD_RETURN_DONE; + } + + buffer[len] = '\0'; + handle_request(client, buffer); + } + + return THREAD_RETURN_DONE; +} + +int create_request_client(int socket_fd) +{ + struct request_client *client; + + client = malloc(sizeof(struct request_client)); + if (!client) { + _E("Failed to allocate memory of request_client"); + return -ENOMEM; + } + + client->id = socket_fd; + client->resource_table = g_hash_table_new(g_int_hash, g_int_equal); + + g_mutex_init(&client->mutex); + + create_daemon_thread(&client->worker, request_handler_func, client); + + add_client_to_list(client); + + return 0; +} + diff --git a/src/monitor/request-server.c b/src/monitor/request-server.c new file mode 100644 index 0000000..27a580e --- /dev/null +++ b/src/monitor/request-server.c @@ -0,0 +1,184 @@ +/* + * PASS (Power Aware System Service) + * + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/** + * @file request-server.c + * @brief TBD + * @ingroup TBD + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define PENDING_MAX 3 +#define REQUEST_SERVER_PORT 10001 + +static bool g_request_server_run; + +const char *request_type_str[] = { + "REQUEST_CREATE_RESOURCE", + "REQUEST_UPDATE_RESOURCE", + "REQUEST_REMOVE_RESOURCE", + "REQUEST_SET_ATTR_INTEREST", + "REQUEST_UNSET_ATTR_INTEREST", + "REQUEST_SET_RESOURCE_CONTROL", + "REQUEST_GET_VALUE_INT", + "REQUEST_GET_RESOURCE_NUM", + "REQUEST_GET_AVAILABLE_ATTRS", +}; + +static int request_server_func(void *ctx, void **result) +{ + struct sockaddr_in address; + struct timeval wait; + int opt = true; + int server_socket; + int addrlen; + int ret; + fd_set fds; + + if (!g_request_server_run) + return THREAD_RETURN_DONE; + + /* 0. initialize server socket */ + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (server_socket < 0) { + _E("Failed to initialize socket"); + goto error_out; + } + + if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, + (char *)&opt, sizeof(opt)) < 0) { + _E("Failed to setsockopt"); + goto error_out_close; + } + + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(REQUEST_SERVER_PORT); + + if (bind(server_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { + _E("Failed to bind"); + goto error_out_close; + } + + if (listen(server_socket, PENDING_MAX) < 0) { + _E("Failed to begin listenning"); + goto error_out_close; + } + + addrlen = sizeof(address); + + while (g_request_server_run) { + FD_ZERO(&fds); + FD_SET(server_socket, &fds); + + wait.tv_sec = 1; + wait.tv_usec = 0; + + ret = select(FD_SETSIZE, &fds, NULL, NULL, &wait); + if (ret < 0) { + _E("failed to select"); + goto error_out_close; + } + + if (FD_ISSET(server_socket, &fds)) { + int new_socket = accept(server_socket, (struct sockaddr *)&address, + (socklen_t *)&addrlen); + + if (new_socket < 0) { + _E("Failed to accept"); + goto error_out_close; + } + + create_request_client(new_socket); + } + } + + close(server_socket); + + return THREAD_RETURN_DONE; + +error_out_close: + close(server_socket); +error_out: + + return THREAD_RETURN_ERROR; +} + +static struct thread *server_thread; + +static int request_server_init_done(void *data, void *user_data) +{ + g_request_server_run = true; + if (create_daemon_thread(&server_thread, request_server_func, NULL)) + _E("Failed to create request_server_thread "); + + return 0; +} + +static void request_server_init(void *data) +{ + /* nothing to do */ +} + +static void request_server_exit(void *data) +{ + unregister_notifier(DEVICE_NOTIFIER_INIT_DONE, request_server_init_done, NULL); + g_request_server_run = false; + destroy_thread(server_thread); +} + +static int request_server_probe(void *data) +{ + int ret = 0; + + ret = register_notifier(DEVICE_NOTIFIER_INIT_DONE, + request_server_init_done, NULL); + if (ret < 0) { + _E("Failed to register a callback function"); + return ret; + } + + return 0; +} + +static const struct device_ops request_server_device_ops = { + .name = "request-server", + .probe = request_server_probe, + .init = request_server_init, + .exit = request_server_exit, +}; + +DEVICE_OPS_REGISTER(&request_server_device_ops); -- 2.7.4 From 145597a3a7e18217bebd834948c851e68dcee5e1 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 7 Mar 2022 16:49:04 +0900 Subject: [PATCH 07/16] lib: tmonitor: Implement tmonitor APIs Tmonitor provides resource monitoring feature by using socket connection. This is the first version of that implements a subset of a tmonitor API set. Change-Id: I9174ba3849f0eae069ace34e9a1b26be0064a436 Signed-off-by: Sung-hun Kim Signed-off-by: Dongwoo Lee --- lib/tmonitor/tmonitor.c | 310 +++++++++++++++++++++++++++++++++++++++++++++--- lib/tmonitor/tmonitor.h | 56 +++++++-- 2 files changed, 339 insertions(+), 27 deletions(-) diff --git a/lib/tmonitor/tmonitor.c b/lib/tmonitor/tmonitor.c index 5b0071d..a5bde45 100644 --- a/lib/tmonitor/tmonitor.c +++ b/lib/tmonitor/tmonitor.c @@ -20,6 +20,23 @@ #define _GNU_SOURCE #include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REQUEST_SERVER_IP "127.0.0.1" +#define REQUEST_SERVER_PORT 10001 extern char *program_invocation_name; @@ -27,27 +44,235 @@ extern char *program_invocation_name; #define EXPORT __attribute__ ((visibility("default"))) #endif +struct tmonitor_client { + int id; + int period; + int (*func)(void *data, void *user_data); + void *user_data; +}; + +#define MAX_BUF_SIZE 1024 + +static GList *g_tmonitor_client_head; +static GMutex g_mutex; + +void add_client_to_list(struct tmonitor_client *client) +{ + if (!client) + return; + + g_mutex_lock(&g_mutex); + g_tmonitor_client_head = + g_list_append(g_tmonitor_client_head, (gpointer)client); + g_mutex_unlock(&g_mutex); +} + +void remove_client_from_list(struct tmonitor_client *client) +{ + if (!client) + return; + + g_mutex_lock(&g_mutex); + g_tmonitor_client_head = + g_list_remove(g_tmonitor_client_head, (gpointer)client); + g_mutex_unlock(&g_mutex); +} + +static struct tmonitor_client *find_client_by_id(int id) +{ + struct tmonitor_client *client; + GList *node; + + for (node = g_tmonitor_client_head; + node != NULL; + node = node->next) { + client = node->data; + if (client->id == id) + return client; + } + + return NULL; +} + EXPORT int tmonitor_init(int period, int (*func)(void *data, void* user_data), void *user_data) { - /* TODO */ - return 0; + struct tmonitor_client *client; + struct sockaddr_in server_addr; + int ret = -EIO; + + client = malloc(sizeof(struct tmonitor_client)); + if (!client) { + _E("[libpass] failed to allocate memory"); + return -ENOMEM; + } + + /* the minimum period is 100ms */ + if (period > 0 || period < 100) + period = 100; + + client->period = period; + client->func = func; + client->user_data = user_data; + + /* open socket to server */ + client->id = socket(AF_INET, SOCK_STREAM, 0); + if (client->id < 0) { + _E("[libpass] socket creation error"); + goto err_out_free; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(REQUEST_SERVER_PORT); + + if (inet_pton(AF_INET, REQUEST_SERVER_IP, &server_addr.sin_addr) <= 0) { + _E("[libpass] invalid address"); + goto err_out_close; + } + + if (connect(client->id, (struct sockaddr *)&server_addr, + sizeof(server_addr)) < 0) { + _E("[libpass] connection failed"); + goto err_out_close; + } + + add_client_to_list(client); + + return client->id; + +err_out_close: + close(client->id); +err_out_free: + free(client); + + return ret; } EXPORT -void tmonitor_exit(int id) +int tmonitor_connect(void) { - /* TODO */ + return tmonitor_init(0, NULL, NULL); } EXPORT -int tmonitor_set_attrs(int id, int resource_type, u_int64_t attr_mask) +int tmonitor_exit(int id) { - /* TODO */ + struct tmonitor_client *client; + + client = find_client_by_id(id); + if (!client) { + _E("[libpass] cannot find client-%d", id); + return -EINVAL; + } + + close(client->id); + remove_client_from_list(client); + free(client); + return 0; } EXPORT +int tmonitor_create_resource(int id, int resource_type) +{ + char buffer[MAX_BUF_SIZE + 1]; + int buffer_len; + int response_req; + int ret; + + buffer_len = sprintf(buffer, "%d:%d", REQUEST_CREATE_RESOURCE, resource_type); + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer for create resource"); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, MAX_BUF_SIZE, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + return -EIO; + } + + buffer[buffer_len] = '\0'; + if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + return -EINVAL; + + if (response_req != REQUEST_CREATE_RESOURCE) { + _E("wrong response"); + return -EINVAL; + } + + return ret; +} + +EXPORT +int tmonitor_set_attr_interest(int id, int resource_id, u_int64_t attr_mask) +{ + char buffer[MAX_BUF_SIZE + 1]; + int buffer_len; + int response_req; + int ret; + + buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + REQUEST_SET_ATTR_INTEREST, resource_id, attr_mask); + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer"); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, MAX_BUF_SIZE, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + return -EIO; + } + + buffer[buffer_len] = '\0'; + if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + return -EINVAL; + + if (response_req != REQUEST_SET_ATTR_INTEREST) { + _E("[libpass] wrong response"); + return -EINVAL; + } + + return ret; +} + +EXPORT +int tmonitor_set_resource_control(int id, int resource_id, u_int64_t ctrl_id, int value) +{ + char buffer[MAX_BUF_SIZE + 1]; + int buffer_len; + int response_req; + int ret; + + buffer_len = sprintf(buffer, "%d:%d:%"PRIu64":%d", + REQUEST_SET_RESOURCE_CONTROL, resource_id, ctrl_id, value); + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer"); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, MAX_BUF_SIZE, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + return -EIO; + } + + buffer[buffer_len] = '\0'; + if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + return -EINVAL; + + if (response_req != REQUEST_SET_RESOURCE_CONTROL) { + _E("[libpass] wrong response"); + return -EINVAL; + } + + return ret; +} +EXPORT int tmonitor_get_available_attrs(int id, int resource_type, int *available_attrs[], int *num_attrs) { @@ -58,33 +283,90 @@ int tmonitor_get_available_attrs(int id, int resource_type, EXPORT int tmonitor_start(int id) { - /* TODO */ return 0; } EXPORT -void tmonitor_stop(int id) +int tmonitor_stop(int id) { - /* TODO */ + return 0; } EXPORT int tmonitor_update(int id) { - /* TODO */ return 0; } EXPORT -int tmonitor_get_value_int(int id, int resource_type, u_int64_t attr) +int tmonitor_update_resource(int id, int resource_id) { - /* TODO */ - return 0; + char buffer[MAX_BUF_SIZE + 1]; + int buffer_len; + int response_req; + int ret; + + buffer_len = sprintf(buffer, "%d:%d", REQUEST_UPDATE_RESOURCE, resource_id); + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer"); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, MAX_BUF_SIZE, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + return -EIO; + } + + buffer[buffer_len] = '\0'; + if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + return -EINVAL; + + if (response_req != REQUEST_UPDATE_RESOURCE) { + _E("[libpass] wrong response"); + return -EINVAL; + } + + return ret; +} + +EXPORT +int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int *value) +{ + char buffer[MAX_BUF_SIZE + 1]; + int buffer_len; + int response_req; + int ret; + + buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + REQUEST_GET_VALUE_INT, resource_id, attr_id); + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer"); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, MAX_BUF_SIZE, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + return -EIO; + } + + buffer[buffer_len] = '\0'; + if (sscanf(buffer, "%d:%d:%d", &response_req, value, &ret) < 3) + return -EINVAL; + + if (response_req != REQUEST_GET_VALUE_INT) { + _E("[libpass] wrong response"); + return -EINVAL; + } + + return ret; } EXPORT int tmonitor_get_resource_num(int id, int resource_type) { - /* TODO */ return 0; } diff --git a/lib/tmonitor/tmonitor.h b/lib/tmonitor/tmonitor.h index 3c4a667..d661db2 100644 --- a/lib/tmonitor/tmonitor.h +++ b/lib/tmonitor/tmonitor.h @@ -118,30 +118,50 @@ extern "C" { int tmonitor_init(int period, int (*func)(void *data, void* user_data), void *user_data); /** + * @brief Initialize the tizen monitor quickly + * @return @c positive integer on success, otherwise a negative error value + */ +int tmonitor_connect(void); + +/** * @brief Exit the tizem monitor * @param[in] Unique id of tizen monitor which be returnted by tmonitor_init + * @return @c 0 on success, otherwise a negative error value + */ +int tmonitor_exit(int id); + +/** + * @brief Alias of tmonitor_exit to provide pair with tmonitor_connect + * @param[in] Unique id of tizen monitor which be returnted by tmonitor_connect + * @return @c 0 on success, otherwise a negative error value + */ +#define tmonitor_disconnect tmonitor_exit + +/** + * @brief Create resource for given resource_type + * @param[in] Unique id of tizen monitor which be returnted by tmonitor_init/connect + * @param[in] Resource type + * @return @c positive integer as resource handler id on success, otherwise a negative error value */ -void tmonitor_exit(int id); +int tmonitor_create_resource(int id, int resource_type); /** * @brief Set the interested attributes for monitoring * @param[in] Unique id of tizen monitor - * @param[in] Resource type + * @param[in] Unique id of resource * @param[in] Attribute mask including the various attributes * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_set_attrs(int id, int resource_type, u_int64_t attr_mask); +int tmonitor_set_attr_interest(int id, int resource_id, u_int64_t attr_mask); /** - * @brief Get the available attribute list according to resource type + * @brief Set the interested attributes for monitoring * @param[in] Unique id of tizen monitor - * @param[in] Resource type - * @param[out] List of available attribute list - * @param[out] Number of available attributes + * @param[in] Unique id of resource + * @param[in] Attribute mask including the various attributes * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_get_available_attrs(int id, int resource_type, - int *available_attrs[], int *num_attrs); +int tmonitor_set_resource_control(int id, int resource_id, u_int64_t ctrl_id, int value); /** * @brief Start tizen monitor with asynchronous method @@ -153,8 +173,9 @@ int tmonitor_start(int id); /** * @brief Stop tizen monitor * @param[in] Unique id of tizen monitor + * @return @c 0 on success, otherwise a negative error value */ -void tmonitor_stop(int id); +int tmonitor_stop(int id); /** * @brief Update value of the interested attributes by tmonitor_set_attrs() @@ -164,13 +185,22 @@ void tmonitor_stop(int id); int tmonitor_update(int id); /** + * @brief Update value of the interested attributes by tmonitor_set_attrs() + * @param[in] Unique id of tizen monitor + * @param[in] Unique id of resource + * @return @c 0 on success, otherwise a negative error value + */ +int tmonitor_update_resource(int id, int resource_id); + +/** * @brief Get integer value of resource attribute * @param[in] Unique id of tizen monitor - * @param[in] Resource type + * @param[in] Unique id of resource * @param[in] Resoruce attribute id - * @return @c positive integer value, otherwise a negative error value + * @param[out] Value retrieved from resource attribute + * @return @ 0 on success, otherwise a negative error value */ -int tmonitor_get_value_int(int id, int resource_type, u_int64_t attr); +int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr, int *value); /** * @brief Get the supported resource number -- 2.7.4 From 42de2718bc68aca959608c82f03733317ab64719 Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Thu, 10 Mar 2022 12:42:57 +0900 Subject: [PATCH 08/16] monitor: remove an unnecessary mutex in request_client resource_table in request_client is only accessed by the owner thread. Thus, such member does not need to be protected from concurrent accesses. Change-Id: I942e9b8a8de3a0bfb1d3a33fc249ebc1c3f2cb56 Signed-off-by: Sung-hun Kim --- include/util/request-handler.h | 1 - src/monitor/request-handler.c | 11 +---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/include/util/request-handler.h b/include/util/request-handler.h index 87f8d0e..d7eadc8 100644 --- a/include/util/request-handler.h +++ b/include/util/request-handler.h @@ -30,7 +30,6 @@ struct request_client { int nr_resources; struct thread *worker; GHashTable *resource_table; - GMutex mutex; }; #define REQUEST_BUFFER_MAX 1000 diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 8082e81..ac0cffd 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -53,19 +53,14 @@ static void finalize_request_client(struct request_client *client) if (!client) return; - if (client->resource_table) { - g_mutex_lock(&client->mutex); + if (client->resource_table) g_hash_table_foreach(client->resource_table, (GHFunc)free_resource, NULL); - g_mutex_unlock(&client->mutex); - } } static void register_resource_to_client(struct request_client *client, struct resource *res) { - g_mutex_lock(&client->mutex); g_hash_table_insert(client->resource_table, (gpointer)&res->id, (gpointer)res); - g_mutex_unlock(&client->mutex); } static struct resource * @@ -73,9 +68,7 @@ get_resource_by_id(struct request_client *client, int resource_id) { struct resource *res; - g_mutex_lock(&client->mutex); res = g_hash_table_lookup(client->resource_table, (gpointer)&resource_id); - g_mutex_unlock(&client->mutex); return res; } @@ -336,8 +329,6 @@ int create_request_client(int socket_fd) client->id = socket_fd; client->resource_table = g_hash_table_new(g_int_hash, g_int_equal); - g_mutex_init(&client->mutex); - create_daemon_thread(&client->worker, request_handler_func, client); add_client_to_list(client); -- 2.7.4 From ad24f810bd0f559d2034bdd0d54bcaa185ac7ebf Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Thu, 10 Mar 2022 14:52:55 +0900 Subject: [PATCH 09/16] monitor: rename the member of request_client Previously, client->id is used as a socket descriptor. It can be a confused situation for future readers. So, rename it to client->socket_fd to reveal the intention of the member variable. Change-Id: I3512da878b412f3b8aa5821c70de254bf5cd64bb Signed-off-by: Sung-hun Kim --- include/util/request-handler.h | 2 +- src/monitor/request-handler.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/util/request-handler.h b/include/util/request-handler.h index d7eadc8..c03adef 100644 --- a/include/util/request-handler.h +++ b/include/util/request-handler.h @@ -26,7 +26,7 @@ extern const char *request_type_str[]; struct request_client { - int id; + int socket_fd; int nr_resources; struct thread *worker; GHashTable *resource_table; diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index ac0cffd..3e54ac9 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -256,7 +256,7 @@ static void handle_request(struct request_client *client, char *buffer) } sprintf(response, "%d", ret); - if (send(client->id, _response, strlen(_response), 0) < 0) + if (send(client->socket_fd, _response, strlen(_response), 0) < 0) _E("Failed to send respones, error: %s", strerror(errno)); } @@ -297,14 +297,14 @@ static int request_handler_func(void *data, void **result) struct request_client *client = (struct request_client *)data; int len; - _D("Start worker thread for client-%d", client->id); + _D("Start worker thread for client-%d", client->socket_fd); while (1) { - len = recv(client->id, buffer, REQUEST_BUFFER_MAX, 0); + len = recv(client->socket_fd, buffer, REQUEST_BUFFER_MAX, 0); if (len == 0) { - _D("Client-%d is disconnected", client->id); + _D("Client-%d is disconnected", client->socket_fd); finalize_request_client(client); - close(client->id); + close(client->socket_fd); destroy_request_client(client); return THREAD_RETURN_DONE; } @@ -326,7 +326,7 @@ int create_request_client(int socket_fd) return -ENOMEM; } - client->id = socket_fd; + client->socket_fd = socket_fd; client->resource_table = g_hash_table_new(g_int_hash, g_int_equal); create_daemon_thread(&client->worker, request_handler_func, client); -- 2.7.4 From 66acc685c2232daaa5a1809eee805385c67b1ca9 Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Thu, 10 Mar 2022 15:55:12 +0900 Subject: [PATCH 10/16] monitor: Replace vulnerable sprintf to snprintf Change-Id: I6baf894343dfa1db050bdf5ac20af735dc7c5185 Signed-off-by: Sung-hun Kim --- src/monitor/request-handler.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 3e54ac9..c27e544 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -206,6 +206,7 @@ static void handle_request(struct request_client *client, char *buffer) char *args; int request_type; int ret, len; + int buffer_len = REQUEST_BUFFER_MAX; request_type = split_request_type_and_args(buffer, &args); @@ -213,8 +214,9 @@ static void handle_request(struct request_client *client, char *buffer) * Format of response * - */ - len = sprintf(response, "%d:", request_type); + len = snprintf(response, buffer_len, "%d:", request_type); response += len; + buffer_len -= len; switch (request_type) { case REQUEST_CREATE_RESOURCE: @@ -245,8 +247,9 @@ static void handle_request(struct request_client *client, char *buffer) if (ret < 0) _D("failed to get value"); - len = sprintf(response, "%d:", value); + len = snprintf(response, buffer_len, "%d:", value); response += len; + buffer_len -= len; } break; default: @@ -254,7 +257,7 @@ static void handle_request(struct request_client *client, char *buffer) ret = -EINVAL; break; } - sprintf(response, "%d", ret); + snprintf(response, buffer_len, "%d", ret); if (send(client->socket_fd, _response, strlen(_response), 0) < 0) _E("Failed to send respones, error: %s", strerror(errno)); -- 2.7.4 From c08c6bba77b3980164a68d6e9a9eb9304224dbba Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 10 Mar 2022 11:57:04 +0900 Subject: [PATCH 11/16] monitor: request: Remove unused request name array Change-Id: Idb1b47964b08b0fefeee8f4bec4eff201c896d0e Signed-off-by: Dongwoo Lee --- include/util/request-handler.h | 2 -- src/monitor/request-server.c | 12 ------------ 2 files changed, 14 deletions(-) diff --git a/include/util/request-handler.h b/include/util/request-handler.h index c03adef..d4e2a5f 100644 --- a/include/util/request-handler.h +++ b/include/util/request-handler.h @@ -23,8 +23,6 @@ #include -extern const char *request_type_str[]; - struct request_client { int socket_fd; int nr_resources; diff --git a/src/monitor/request-server.c b/src/monitor/request-server.c index 27a580e..c1bf04a 100644 --- a/src/monitor/request-server.c +++ b/src/monitor/request-server.c @@ -46,18 +46,6 @@ static bool g_request_server_run; -const char *request_type_str[] = { - "REQUEST_CREATE_RESOURCE", - "REQUEST_UPDATE_RESOURCE", - "REQUEST_REMOVE_RESOURCE", - "REQUEST_SET_ATTR_INTEREST", - "REQUEST_UNSET_ATTR_INTEREST", - "REQUEST_SET_RESOURCE_CONTROL", - "REQUEST_GET_VALUE_INT", - "REQUEST_GET_RESOURCE_NUM", - "REQUEST_GET_AVAILABLE_ATTRS", -}; - static int request_server_func(void *ctx, void **result) { struct sockaddr_in address; -- 2.7.4 From 1d3c7321774a59eb981af743b9cfa2c80df53f53 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 10 Mar 2022 16:44:39 +0900 Subject: [PATCH 12/16] monitor: request-handler: Handle negative return value of recv Change-Id: I4a84b3f834fbc4f036f28597aa34f0bceb9d6c5c Signed-off-by: Dongwoo Lee --- src/monitor/request-handler.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index c27e544..2fdd58a 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -306,15 +306,21 @@ static int request_handler_func(void *data, void **result) len = recv(client->socket_fd, buffer, REQUEST_BUFFER_MAX, 0); if (len == 0) { _D("Client-%d is disconnected", client->socket_fd); - finalize_request_client(client); - close(client->socket_fd); - destroy_request_client(client); - return THREAD_RETURN_DONE; + goto out; + } + + if (len < 0) { + _E("Error occurs while receiving request: %s", strerror(errno)); + goto out; } buffer[len] = '\0'; handle_request(client, buffer); } +out: + finalize_request_client(client); + close(client->socket_fd); + destroy_request_client(client); return THREAD_RETURN_DONE; } -- 2.7.4 From d5cdf45ffac60078b731f61e8c73ebf02cdc5de5 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 10 Mar 2022 12:15:56 +0900 Subject: [PATCH 13/16] monitor: handler: Fix wrong argument type Change-Id: Iae4bee8a05313ff1ebd4e1de1892c7bf37af8c71 Signed-off-by: Dongwoo Lee --- include/util/resource.h | 2 +- src/util/resource.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/util/resource.h b/include/util/resource.h index a794e58..030a75e 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -167,7 +167,7 @@ get_resource_attr_value(struct resource *resource, u_int64_t attr_id); int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data); int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_t *data); int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32_t *data); -int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int32_t *data); +int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int64_t *data); int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double *data); int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char **data); int put_resource_attr_string(struct resource *resource, u_int64_t attr_id); diff --git a/src/util/resource.c b/src/util/resource.c index 8e16332..280c2f9 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -352,7 +352,7 @@ int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32 return 0; } -int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int32_t *data) +int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int64_t *data) { struct resource_attribute_value *attr_value = NULL; -- 2.7.4 From 6e91d68ad4ade7415b4d3bdb515826c45fb961b1 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 10 Mar 2022 16:16:23 +0900 Subject: [PATCH 14/16] util: resource: Fix type check errors Change-Id: Ie4f3a00893aa4c3a87c5e83eb763135efc965cf1 Signed-off-by: Dongwoo Lee --- src/util/resource.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/resource.c b/src/util/resource.c index 280c2f9..535148a 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -324,7 +324,7 @@ int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_ { struct resource_attribute_value *attr_value = NULL; - if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT)) + if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT64)) return -EINVAL; attr_value = get_resource_attr_value(resource, attr_id); @@ -340,7 +340,7 @@ int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32 { struct resource_attribute_value *attr_value = NULL; - if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT)) + if (!check_attr_validate(resource, attr_id, DATA_TYPE_UINT)) return -EINVAL; attr_value = get_resource_attr_value(resource, attr_id); @@ -356,7 +356,7 @@ int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int { struct resource_attribute_value *attr_value = NULL; - if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT)) + if (!check_attr_validate(resource, attr_id, DATA_TYPE_UINT64)) return -EINVAL; attr_value = get_resource_attr_value(resource, attr_id); -- 2.7.4 From 069a78cd05a00d389768c415226466bbe8242e7a Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 7 Mar 2022 17:48:49 +0900 Subject: [PATCH 15/16] util: resource: Rework double type attributes To support double type attributes with exact precison, instead of casting double to void pointer, using double type allocated memory as like string or array. Change-Id: Ie432026f02ad0d22b98a24fdeed7ae1ddf5440ef Signed-off-by: Dongwoo Lee --- include/util/resource.h | 3 ++- src/resource/resource-display.c | 10 +++++++++- src/resource/resource-system.c | 12 ++++++++---- src/util/resource.c | 21 +++++++++++++++++++-- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/include/util/resource.h b/include/util/resource.h index 030a75e..527e466 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -168,7 +168,8 @@ int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_t *data); int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32_t *data); int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int64_t *data); -int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double *data); +int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double **data); +int put_resource_attr_double(struct resource *resource, u_int64_t attr_id); int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char **data); int put_resource_attr_string(struct resource *resource, u_int64_t attr_id); int get_resource_attr_array(struct resource *resource, u_int64_t attr_id, diff --git a/src/resource/resource-display.c b/src/resource/resource-display.c index f3b7af9..2b95337 100644 --- a/src/resource/resource-display.c +++ b/src/resource/resource-display.c @@ -56,6 +56,7 @@ static int display_get_fps(const struct resource *res, GError *err = NULL; struct display_fps_data fps_data; int *disp_id; + double *fps; int ret = 0; if (!res || !res->priv || !attr || !data) @@ -112,7 +113,14 @@ static int display_get_fps(const struct resource *res, &fps_data.window, &fps_data.fps); out: - *data = (void *)(intptr_t)fps_data.fps; + fps = malloc(sizeof(double)); + if (!fps) { + ret = -ENOMEM; + goto err_reply; + } + + *fps = fps_data.fps; + *data = (void *)fps; err_reply: g_object_unref(reply); diff --git a/src/resource/resource-system.c b/src/resource/resource-system.c index e62b6d2..46bd145 100644 --- a/src/resource/resource-system.c +++ b/src/resource/resource-system.c @@ -82,19 +82,23 @@ static int system_get_avg_cpu_util(const struct resource *res, void **data) { struct system_resouce_data *sysdata; - double util; + double *util; if (!res || !res->priv ||!attr || !data) return -EINVAL; + util = malloc(sizeof(double)); + if (!util) + return -ENOMEM; + sysdata = (struct system_resouce_data *)res->priv; - util = __calculate_cpu_util(attr->id, &sysdata->prev_avg, &sysdata->curr_avg); + *util = __calculate_cpu_util(attr->id, &sysdata->prev_avg, &sysdata->curr_avg); if (util < 0) { _W("failed to calculate average cpu util (%s: %s)\n", res->name, attr->name); - util = 0; + *util = 0.0; } - *data = (void *)(intptr_t)util; + *data = (void *)util; return 0; } diff --git a/src/util/resource.c b/src/util/resource.c index 535148a..4128e97 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -368,7 +368,7 @@ int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int return 0; } -int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double *data) +int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double **data) { struct resource_attribute_value *attr_value = NULL; @@ -379,7 +379,24 @@ int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, doubl if (!attr_value) return -EINVAL; - *data = (double)(intptr_t)attr_value->data; + *data = (double *)attr_value->data; + + return 0; +} + +int put_resource_attr_double(struct resource *resource, u_int64_t attr_id) +{ + struct resource_attribute_value *attr_value = NULL; + + if (!check_attr_validate(resource, attr_id, DATA_TYPE_DOUBLE)) + return -EINVAL; + + attr_value = get_resource_attr_value(resource, attr_id); + if (!attr_value) + return -EINVAL; + + free(attr_value->data); + attr_value->data = NULL; return 0; } -- 2.7.4 From 99870d8f63e9794f933bfb1d566ec7d27a982538 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 10 Mar 2022 20:32:21 +0900 Subject: [PATCH 16/16] util: resource: Allocate storage for attribute data at set interest This introduces the new way to using attribute value. Instead of allocate memory for each attribute value by driver-self, memory is allocated when client sets interest for each attribute. This can prevent from unnecessary memory allocation by deferring until it is really required. Change-Id: Ie6d47db4c6735510a0e784f8c254705c2c176b25 Signed-off-by: Dongwoo Lee --- include/util/resource.h | 10 +-- lib/tmonitor/tmonitor.h | 6 +- src/resource/resource-battery.c | 17 ++-- src/resource/resource-bus.c | 148 +++++++------------------------ src/resource/resource-cpu.c | 152 +++++++------------------------- src/resource/resource-display.c | 11 +-- src/resource/resource-gpu.c | 150 +++++++------------------------- src/resource/resource-memory.c | 71 +++------------ src/resource/resource-process.c | 130 +++++++++++----------------- src/resource/resource-system.c | 39 ++++----- src/util/resource.c | 187 ++++++++++++++++++++++------------------ 11 files changed, 286 insertions(+), 635 deletions(-) diff --git a/include/util/resource.h b/include/util/resource.h index 527e466..9290a29 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -58,7 +58,7 @@ struct resource_attribute_ops { const void *data, int count); int (*get)(const struct resource *res, const struct resource_attribute *attr, - void **data); + void *data); }; struct resource_attribute { @@ -168,15 +168,11 @@ int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_t *data); int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32_t *data); int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int64_t *data); -int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double **data); -int put_resource_attr_double(struct resource *resource, u_int64_t attr_id); -int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char **data); -int put_resource_attr_string(struct resource *resource, u_int64_t attr_id); +int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double *data); +int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char *data); int get_resource_attr_array(struct resource *resource, u_int64_t attr_id, struct array_value **data); -int put_resource_attr_array(struct resource *resource, u_int64_t attr_id); int get_resource_attr_ptr(struct resource *resource, u_int64_t attr_id, void **data); -int put_resource_attr_ptr(struct resource *resource, u_int64_t attr_id); void set_resource_attr_interest(struct resource *resource, u_int64_t interest_mask); void unset_resource_attr_interest(struct resource *resource, u_int64_t interest_mask); diff --git a/lib/tmonitor/tmonitor.h b/lib/tmonitor/tmonitor.h index d661db2..b3bbeca 100644 --- a/lib/tmonitor/tmonitor.h +++ b/lib/tmonitor/tmonitor.h @@ -101,9 +101,9 @@ extern "C" { #define PROCESS_CPU_UTIL BIT(0) #define PROCESS_MEM_VIRT BIT(1) #define PROCESS_MEM_RSS BIT(2) -#define PROCESS_MEM_PERCENT BIT(3) -#define PROCESS_DISK_READ BIT(4) -#define PROCESS_DISK_WRITE BIT(5) +#define PROCESS_MEM_RSS_PERCENT BIT(3) +#define PROCESS_DISK_READ_BPS BIT(4) +#define PROCESS_DISK_WRITE_BPS BIT(5) #define PROCESS_COMM BIT(6) #define PROCESS_CTRL_TGID BIT(0) diff --git a/src/resource/resource-battery.c b/src/resource/resource-battery.c index d621c37..ded8667 100644 --- a/src/resource/resource-battery.c +++ b/src/resource/resource-battery.c @@ -32,10 +32,11 @@ static int battery_get_info(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { char *path = NULL; - int ret, val = 0; + int ret; + int *val = (int *)data; if (!res || !attr || !data) return -EINVAL; @@ -63,20 +64,18 @@ static int battery_get_info(const struct resource *res, return -EINVAL; } - ret = sysfs_get_int(path, &val); + ret = sysfs_get_int(path, val); if (ret < 0) return ret; - *data = (void *)(intptr_t)val; - return 0; } static int battery_get_status(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { - char buf[BUFF_MAX]; + char *buf = (char *)data; int ret; if (!res || !attr || !data) @@ -86,10 +85,6 @@ static int battery_get_status(const struct resource *res, if (ret < 0) return ret; - *data = strdup(buf); - if (!*data) - return -ENOMEM; - return 0; } diff --git a/src/resource/resource-bus.c b/src/resource/resource-bus.c index 9ca48d9..1fc5fe3 100644 --- a/src/resource/resource-bus.c +++ b/src/resource/resource-bus.c @@ -37,12 +37,13 @@ struct bus_context { int index; }; -static int bus_get_cur_freq(const struct resource *res, +static int bus_get_value_from_hal_power(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct bus_context *ctx; - int val; + int *val = (int *)data; + int _val; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -54,125 +55,40 @@ static int bus_get_cur_freq(const struct resource *res, return -EINVAL; } - val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int bus_get_min_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct bus_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); + switch (attr->id) { + case BUS_CUR_FREQ: + _val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); + break; + case BUS_MIN_FREQ: + _val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); + break; + case BUS_MAX_FREQ: + _val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name); + break; + case BUS_AVAILABLE_MIN_FREQ: + _val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); + break; + case BUS_AVAILABLE_MAX_FREQ: + _val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); + break; + default: return -EINVAL; } - val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); - if (val < 0) + if (_val < 0) return -EINVAL; - *data = (void *)(intptr_t)val; - - return 0; -} - -static int bus_get_max_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct bus_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int bus_get_available_min_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct bus_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int bus_get_available_max_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct bus_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: BUS_CTRL_DEVICE_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; + *val = _val; return 0; } static int bus_get_curr_governor(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct bus_context *ctx; - char buf[BUFF_MAX]; + char *buf = (char *)data; int val; if (!res || !res->priv || !attr || !data) @@ -189,10 +105,6 @@ static int bus_get_curr_governor(const struct resource *res, if (val < 0) return -EINVAL; - *data = strdup(buf); - if (!*data) - return -ENOMEM; - return 0; } @@ -202,35 +114,35 @@ static const struct resource_attribute bus_attrs[] = { .id = BUS_CUR_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = bus_get_cur_freq, + .get = bus_get_value_from_hal_power, }, }, { .name = "BUS_MIN_FREQ", .id = BUS_MIN_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = bus_get_min_freq, + .get = bus_get_value_from_hal_power, }, }, { .name = "BUS_MAX_FREQ", .id = BUS_MAX_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = bus_get_max_freq, + .get = bus_get_value_from_hal_power, } }, { .name = "BUS_AVAILABLE_MIN_FREQ", .id = BUS_AVAILABLE_MIN_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = bus_get_available_min_freq, + .get = bus_get_value_from_hal_power, } }, { .name = "BUS_AVAILABLE_MAX_FREQ", .id = BUS_AVAILABLE_MAX_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = bus_get_available_max_freq, + .get = bus_get_value_from_hal_power, } }, { .name = "BUS_CUR_GOVERNOR", diff --git a/src/resource/resource-cpu.c b/src/resource/resource-cpu.c index 9930016..4527f2c 100644 --- a/src/resource/resource-cpu.c +++ b/src/resource/resource-cpu.c @@ -37,12 +37,13 @@ struct cpu_context { int index; }; -static int cpu_get_cur_freq(const struct resource *res, +static int cpu_get_value_from_hal_power(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct cpu_context *ctx; - int val; + int *val = (int *)data; + int _val; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -54,125 +55,40 @@ static int cpu_get_cur_freq(const struct resource *res, return -EINVAL; } - val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int cpu_get_min_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct cpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); + switch (attr->id) { + case CPU_CUR_FREQ: + _val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); + break; + case CPU_MIN_FREQ: + _val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); + break; + case CPU_MAX_FREQ: + _val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name); + break; + case CPU_AVAILABLE_MIN_FREQ: + _val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); + break; + case CPU_AVAILABLE_MAX_FREQ: + _val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); + break; + default: return -EINVAL; } - val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); - if (val < 0) + if (_val < 0) return -EINVAL; - *data = (void *)(intptr_t)val; - - return 0; -} - -static int cpu_get_max_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct cpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int cpu_get_available_min_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct cpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int cpu_get_available_max_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct cpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: CPU_CTRL_CLUSTER_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; + *val = _val; return 0; } static int cpu_get_curr_governor(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct cpu_context *ctx; - char buf[BUFF_MAX]; + char *buf = (char *)data; int val; if (!res || !res->priv || !attr || !data) @@ -189,23 +105,19 @@ static int cpu_get_curr_governor(const struct resource *res, if (val < 0) return -EINVAL; - *data = strdup(buf); - if (!*data) - return -ENOMEM; - return 0; } static int cpu_get_online_cpu(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { return 0; } static int cpu_get_temperature(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { return 0; } @@ -216,35 +128,35 @@ static const struct resource_attribute cpu_attrs[] = { .id = CPU_CUR_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = cpu_get_cur_freq, + .get = cpu_get_value_from_hal_power, }, }, { .name = "CPU_MIN_FREQ", .id = CPU_MIN_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = cpu_get_min_freq, + .get = cpu_get_value_from_hal_power, }, }, { .name = "CPU_MAX_FREQ", .id = CPU_MAX_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = cpu_get_max_freq, + .get = cpu_get_value_from_hal_power, } }, { .name = "CPU_AVAILABLE_MIN_FREQ", .id = CPU_AVAILABLE_MIN_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = cpu_get_available_min_freq, + .get = cpu_get_value_from_hal_power, } }, { .name = "CPU_AVAILABLE_MAX_FREQ", .id = CPU_AVAILABLE_MAX_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = cpu_get_available_max_freq, + .get = cpu_get_value_from_hal_power, } }, { .name = "CPU_CUR_GOVERNOR", diff --git a/src/resource/resource-display.c b/src/resource/resource-display.c index 2b95337..cbce0c9 100644 --- a/src/resource/resource-display.c +++ b/src/resource/resource-display.c @@ -48,7 +48,7 @@ struct display_fps_data { static int display_get_fps(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { GDBusConnection *conn; GDBusMessage *msg, *reply; @@ -56,7 +56,7 @@ static int display_get_fps(const struct resource *res, GError *err = NULL; struct display_fps_data fps_data; int *disp_id; - double *fps; + double *fps = (double *)data; int ret = 0; if (!res || !res->priv || !attr || !data) @@ -113,14 +113,7 @@ static int display_get_fps(const struct resource *res, &fps_data.window, &fps_data.fps); out: - fps = malloc(sizeof(double)); - if (!fps) { - ret = -ENOMEM; - goto err_reply; - } - *fps = fps_data.fps; - *data = (void *)fps; err_reply: g_object_unref(reply); diff --git a/src/resource/resource-gpu.c b/src/resource/resource-gpu.c index 1c27599..561e745 100644 --- a/src/resource/resource-gpu.c +++ b/src/resource/resource-gpu.c @@ -37,12 +37,13 @@ struct gpu_context { int index; }; -static int gpu_get_cur_freq(const struct resource *res, +static int gpu_get_value_from_hal_power(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct gpu_context *ctx; - int val; + int *val = (int *)data; + int _val; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -54,125 +55,40 @@ static int gpu_get_cur_freq(const struct resource *res, return -EINVAL; } - val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int gpu_get_min_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct gpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); + switch (attr->id) { + case GPU_CUR_FREQ: + _val = hal_power_dvfs_get_curr_freq(res->type, ctx->device_name); + break; + case GPU_MIN_FREQ: + _val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); + break; + case GPU_MAX_FREQ: + _val = hal_power_dvfs_get_max_freq(res->type, ctx->device_name); + break; + case GPU_AVAILABLE_MIN_FREQ: + _val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); + break; + case GPU_AVAILABLE_MAX_FREQ: + _val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); + break; + default: return -EINVAL; } - val = hal_power_dvfs_get_min_freq(res->type, ctx->device_name); - if (val < 0) + if (_val < 0) return -EINVAL; - *data = (void *)(intptr_t)val; - - return 0; -} - -static int gpu_get_max_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct gpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int gpu_get_available_min_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct gpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_available_min_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int gpu_get_available_max_freq(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct gpu_context *ctx; - int val; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->device_name) { - _E("%s: GPU_CTRL_DEVICE_ID is not yet initialized\n", res->name); - return -EINVAL; - } - - val = hal_power_dvfs_get_available_max_freq(res->type, ctx->device_name); - if (val < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; + *val = _val; return 0; } static int gpu_get_curr_governor(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct gpu_context *ctx; - char buf[BUFF_MAX]; + char *buf = (char *)data; int val; if (!res || !res->priv || !attr || !data) @@ -189,16 +105,12 @@ static int gpu_get_curr_governor(const struct resource *res, if (val < 0) return -EINVAL; - *data = strdup(buf); - if (!*data) - return -ENOMEM; - return 0; } static int gpu_get_temperature(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { return 0; } @@ -209,35 +121,35 @@ static const struct resource_attribute gpu_attrs[] = { .id = GPU_CUR_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = gpu_get_cur_freq, + .get = gpu_get_value_from_hal_power, }, }, { .name = "GPU_MIN_FREQ", .id = GPU_MIN_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = gpu_get_min_freq, + .get = gpu_get_value_from_hal_power, }, }, { .name = "GPU_MAX_FREQ", .id = GPU_MAX_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = gpu_get_max_freq, + .get = gpu_get_value_from_hal_power, } }, { .name = "GPU_AVAILABLE_MIN_FREQ", .id = GPU_AVAILABLE_MIN_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = gpu_get_available_min_freq, + .get = gpu_get_value_from_hal_power, } }, { .name = "GPU_AVAILABLE_MAX_FREQ", .id = GPU_AVAILABLE_MAX_FREQ, .type = DATA_TYPE_INT, .ops = { - .get = gpu_get_available_max_freq, + .get = gpu_get_value_from_hal_power, } }, { .name = "GPU_CUR_GOVERNOR", diff --git a/src/resource/resource-memory.c b/src/resource/resource-memory.c index 74c8fd4..f86eb93 100644 --- a/src/resource/resource-memory.c +++ b/src/resource/resource-memory.c @@ -36,11 +36,17 @@ #define PROC_MEM_INFO_MEM_AVAILABLE "MemAvailable" #define PROC_MEM_INFO_MEM_FREE "MemFree" -static inline int memory_read_val_from_proc_node(uint32_t val_id, u_int64_t *val) +static int memory_get_memory_info(const struct resource *res, + const struct resource_attribute *attr, + void *data) { + u_int64_t *val = (u_int64_t *)data; int ret; - switch (val_id) { + if (!res || !attr || !data) + return -EINVAL; + + switch (attr->id) { case MEMORY_TOTAL: ret = kernel_get_memory_total(val); break; @@ -54,64 +60,9 @@ static inline int memory_read_val_from_proc_node(uint32_t val_id, u_int64_t *val _E("wrong memory resource attribute\n"); ret = -EINVAL; } - - return ret; -} - -static int memory_get_total_memory(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - u_int64_t val; - int ret; - - if (!res || !attr || !data) - return -EINVAL; - - ret = memory_read_val_from_proc_node(attr->id, &val); if (ret < 0) return -EINVAL; - *data = (void *)(intptr_t)val; - - return 0; -} - -static int memory_get_available_memory(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - u_int64_t val; - int ret; - - if (!res || !attr || !data) - return -EINVAL; - - ret = memory_read_val_from_proc_node(attr->id, &val); - if (ret < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - - return 0; -} - -static int memory_get_free_memory(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - u_int64_t val; - int ret; - - if (!res || !attr || !data) - return -EINVAL; - - ret = memory_read_val_from_proc_node(attr->id, &val); - if (ret < 0) - return -EINVAL; - - *data = (void *)(intptr_t)val; - return 0; } @@ -121,21 +72,21 @@ static const struct resource_attribute memory_attrs[] = { .id = MEMORY_TOTAL, .type = DATA_TYPE_UINT64, .ops = { - .get = memory_get_total_memory, + .get = memory_get_memory_info, }, }, { .name = "MEMORY_AVAILABLE", .id = MEMORY_AVAILABLE, .type = DATA_TYPE_UINT64, .ops = { - .get = memory_get_available_memory, + .get = memory_get_memory_info, }, }, { .name = "MEMORY_FREE", .id = MEMORY_FREE, .type = DATA_TYPE_UINT64, .ops = { - .get = memory_get_free_memory, + .get = memory_get_memory_info, } }, }; diff --git a/src/resource/resource-process.c b/src/resource/resource-process.c index 1c28294..728d8be 100644 --- a/src/resource/resource-process.c +++ b/src/resource/resource-process.c @@ -44,11 +44,11 @@ static long jiffy; static int process_get_cpu_util(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct process_context *ctx; struct taskstats *prev, *curr; - double util = 0.0; + double *util = (double *)data; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -64,30 +64,22 @@ static int process_get_cpu_util(const struct resource *res, curr = &ctx->curr; if (ctx->cpu_period >= 1E-6) { - util = (double)(curr->ac_utime + curr->ac_stime); - util -= (double)(prev->ac_utime + prev->ac_stime); - util *= (jiffy / (ctx->cpu_period * 10.0)); - - /* - * To obtain precision after converting types between double and - * void pointer, utilization increased 1000 times (0~100000), so - * value should be divided by 1000 at user-side. - */ - util = min(util, 100000.0); + *util = (double)(curr->ac_utime + curr->ac_stime); + *util -= (double)(prev->ac_utime + prev->ac_stime); + *util *= (jiffy / (ctx->cpu_period * 10000.0)); + *util = min(*util, 100.0); } - *data = (void *)(intptr_t)(int)util; - return 0; } static int process_get_mem_virt(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct process_context *ctx; struct taskstats *curr; - double virt; + u_int64_t *virt = (u_int64_t *)data; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -101,21 +93,18 @@ static int process_get_mem_virt(const struct resource *res, curr = &ctx->curr; - virt = (double)curr->virtmem / (double)curr->ac_stime; - virt *= 1024.0 * 1000.0; - - *data = (void *)(uintptr_t)(int)virt; + *virt = (curr->virtmem * 1024 * 1024) / curr->ac_stime; return 0; } static int process_get_mem_rss(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct process_context *ctx; struct taskstats *curr; - double rss; + u_int64_t _rss; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -129,17 +118,23 @@ static int process_get_mem_rss(const struct resource *res, curr = &ctx->curr; - rss = (double)curr->coremem / (double)curr->ac_stime; - rss *= 1024.0 * 1000.0; + _rss = (curr->coremem * 1024 * 1024) / curr->ac_stime; switch (attr->id) { case PROCESS_MEM_RSS: - *data = (void *)(intptr_t)(int)rss; + { + u_int64_t *rss = (u_int64_t *)data; + + *rss = _rss; break; - case PROCESS_MEM_PERCENT: - /* percentage value should be divided by 1000 at user-side */ - *data = (void *)(intptr_t)(int)((rss / ctx->total_memory) * 100000.0); + } + case PROCESS_MEM_RSS_PERCENT: + { + double *percent = (double *)data; + + *percent = ((double)_rss / (double)ctx->total_memory) * 100.0; break; + } default: return -EINVAL; } @@ -147,14 +142,14 @@ static int process_get_mem_rss(const struct resource *res, return 0; } -static int process_get_disk_read(const struct resource *res, +static int process_get_disk_bps(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct process_context *ctx; struct taskstats *prev, *curr; u_int64_t period; - double bps = 0.0; + u_int32_t *bps = (u_int32_t *)data; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -170,49 +165,26 @@ static int process_get_disk_read(const struct resource *res, curr = &ctx->curr; period = curr->ac_etime - prev->ac_etime; - bps = (double)(curr->read_bytes - prev->read_bytes) * 1000000 / period; - *data = (void *)(intptr_t)(int)bps; - - return 0; -} - -static int process_get_disk_write(const struct resource *res, - const struct resource_attribute *attr, - void **data) -{ - struct process_context *ctx; - struct taskstats *prev, *curr; - u_int64_t period; - double bps = 0.0; - - if (!res || !res->priv || !attr || !data) - return -EINVAL; - - ctx = res->priv; - - if (!ctx->tgid) { - _E("resource %s is not yet initialized\n", res->name); + switch (attr->id) { + case PROCESS_DISK_READ_BPS: + *bps = (curr->read_bytes - prev->read_bytes) * 1000000 / period; + break; + case PROCESS_DISK_WRITE_BPS: + *bps = (curr->write_bytes - prev->write_bytes) * 1000000 / period; + break; + default: return -EINVAL; } - - prev = &ctx->prev; - curr = &ctx->curr; - - period = curr->ac_etime - prev->ac_etime; - - bps = (double)(curr->write_bytes - prev->write_bytes) * 1000000 / period; - - *data = (void *)(intptr_t)(int)bps; - return 0; } static int process_get_comm(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct process_context *ctx; + char *buf = (char *)data; if (!res || !res->priv || !attr || !data) return -EINVAL; @@ -224,7 +196,7 @@ static int process_get_comm(const struct resource *res, return -EINVAL; } - *data = g_strdup(ctx->comm); + strncpy(buf, ctx->comm, TS_COMM_LEN); return 0; } @@ -233,7 +205,7 @@ static const struct resource_attribute process_attrs[] = { { .name = "PROCESS_CPU_UTIL", .id = PROCESS_CPU_UTIL, - .type = DATA_TYPE_INT, + .type = DATA_TYPE_DOUBLE, .ops = { .get = process_get_cpu_util, }, @@ -241,7 +213,7 @@ static const struct resource_attribute process_attrs[] = { { .name = "PROCESS_MEM_VIRT", .id = PROCESS_MEM_VIRT, - .type = DATA_TYPE_INT, + .type = DATA_TYPE_UINT64, .ops = { .get = process_get_mem_virt, }, @@ -249,33 +221,33 @@ static const struct resource_attribute process_attrs[] = { { .name = "PROCESS_MEM_RSS", .id = PROCESS_MEM_RSS, - .type = DATA_TYPE_INT, + .type = DATA_TYPE_UINT64, .ops = { .get = process_get_mem_rss, }, }, { - .name = "PROCESS_MEM_PERCENT", - .id = PROCESS_MEM_PERCENT, - .type = DATA_TYPE_INT, + .name = "PROCESS_MEM_RSS_PERCENT", + .id = PROCESS_MEM_RSS_PERCENT, + .type = DATA_TYPE_DOUBLE, .ops = { .get = process_get_mem_rss, }, }, { - .name = "PROCESS_DISK_READ", - .id = PROCESS_DISK_READ, - .type = DATA_TYPE_INT, + .name = "PROCESS_DISK_READ_BPS", + .id = PROCESS_DISK_READ_BPS, + .type = DATA_TYPE_UINT, .ops = { - .get = process_get_disk_read, + .get = process_get_disk_bps, }, }, { - .name = "PROCESS_DISK_WRITE", - .id = PROCESS_DISK_WRITE, - .type = DATA_TYPE_INT, + .name = "PROCESS_DISK_WRITE_BPS", + .id = PROCESS_DISK_WRITE_BPS, + .type = DATA_TYPE_UINT, .ops = { - .get = process_get_disk_write, + .get = process_get_disk_bps, }, }, { diff --git a/src/resource/resource-system.c b/src/resource/resource-system.c index 46bd145..8375fe9 100644 --- a/src/resource/resource-system.c +++ b/src/resource/resource-system.c @@ -79,36 +79,31 @@ static double __calculate_cpu_util(int64_t id, struct cpu_stat *prev, static int system_get_avg_cpu_util(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct system_resouce_data *sysdata; - double *util; + double *util = (double *)data; if (!res || !res->priv ||!attr || !data) return -EINVAL; - util = malloc(sizeof(double)); - if (!util) - return -ENOMEM; - sysdata = (struct system_resouce_data *)res->priv; *util = __calculate_cpu_util(attr->id, &sysdata->prev_avg, &sysdata->curr_avg); - if (util < 0) { + if (*util < 0) { _W("failed to calculate average cpu util (%s: %s)\n", res->name, attr->name); *util = 0.0; } - *data = (void *)util; return 0; } static int system_get_per_cpu_util(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { struct system_resouce_data *sysdata; - struct array_value *array; + struct array_value *array = (struct array_value *)data; double *utils; int i; @@ -117,17 +112,16 @@ static int system_get_per_cpu_util(const struct resource *res, sysdata = (struct system_resouce_data *)res->priv; - array = calloc(1, sizeof(*array)); - if (!array) - return -ENOMEM; - array->type = DATA_TYPE_DOUBLE; array->length = sysdata->num_possible_cpus; + + if (array->data) + free(array->data); + array->data = calloc(sysdata->num_possible_cpus, sizeof(double)); - if (!array->data) { - free(array); + if (!array->data) return -ENOMEM; - } + utils = (double *)array->data; for (i = 0; i < sysdata->num_possible_cpus; i++) { @@ -139,33 +133,30 @@ static int system_get_per_cpu_util(const struct resource *res, utils[i] = 0; } } - *data = (void *)array; return 0; } static int system_get_cpu_num(const struct resource *res, const struct resource_attribute *attr, - void **data) + void *data) { - int cpu_num; + int *cpu_num = (int *)data; if (!res || !attr || !data) return -EINVAL; switch (attr->id) { case SYSTEM_POSSIBLE_CPU: - cpu_num = kernel_get_online_cpu_num(); + *cpu_num = kernel_get_online_cpu_num(); break; case SYSTEM_ONLINE_CPU: - cpu_num = kernel_get_possible_cpu_num(); + *cpu_num = kernel_get_possible_cpu_num(); break; default: return -EINVAL; } - *data = (void *)(intptr_t)cpu_num; - return 0; } diff --git a/src/util/resource.c b/src/util/resource.c index 4128e97..9e25238 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -231,12 +231,13 @@ static int update_resource_attr(struct resource *resource, u_int64_t attr_id) return -EINVAL; attr = &resource->attrs[attr_index]; - attr_value = &resource->attrs_value[attr_index]; if (!attr->ops.get) return -EINVAL; - ret = attr->ops.get(resource, attr, &(attr_value->data)); + attr_value = &resource->attrs_value[attr_index]; + + ret = attr->ops.get(resource, attr, attr_value->data); if (ret < 0) return ret; @@ -315,7 +316,7 @@ int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t if (!attr_value) return -EINVAL; - *data = (int32_t)(intptr_t)attr_value->data; + *data = *((int32_t *)attr_value->data); return 0; } @@ -331,7 +332,7 @@ int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_ if (!attr_value) return -EINVAL; - *data = (int64_t)(intptr_t)attr_value->data; + *data = *((int64_t *)attr_value->data); return 0; } @@ -347,7 +348,7 @@ int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32 if (!attr_value) return -EINVAL; - *data = (u_int32_t)(intptr_t)attr_value->data; + *data = *((u_int32_t *)attr_value->data); return 0; } @@ -363,12 +364,12 @@ int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int if (!attr_value) return -EINVAL; - *data = (u_int64_t)(intptr_t)attr_value->data; + *data = *((u_int64_t *)attr_value->data); return 0; } -int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double **data) +int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double *data) { struct resource_attribute_value *attr_value = NULL; @@ -379,29 +380,12 @@ int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, doubl if (!attr_value) return -EINVAL; - *data = (double *)attr_value->data; + *data = *((double *)attr_value->data); return 0; } -int put_resource_attr_double(struct resource *resource, u_int64_t attr_id) -{ - struct resource_attribute_value *attr_value = NULL; - - if (!check_attr_validate(resource, attr_id, DATA_TYPE_DOUBLE)) - return -EINVAL; - - attr_value = get_resource_attr_value(resource, attr_id); - if (!attr_value) - return -EINVAL; - - free(attr_value->data); - attr_value->data = NULL; - - return 0; -} - -int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char **data) +int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char *data) { struct resource_attribute_value *attr_value = NULL; @@ -412,24 +396,7 @@ int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char if (!attr_value) return -EINVAL; - *data = (char *)attr_value->data; - - return 0; -} - -int put_resource_attr_string(struct resource *resource, u_int64_t attr_id) -{ - struct resource_attribute_value *attr_value = NULL; - - if (!check_attr_validate(resource, attr_id, DATA_TYPE_STRING)) - return -EINVAL; - - attr_value = get_resource_attr_value(resource, attr_id); - if (!attr_value || !attr_value->data) - return -EINVAL; - - free(attr_value->data); - attr_value->data = NULL; + strncpy(data, (char *)attr_value->data, BUFF_MAX); return 0; } @@ -450,31 +417,6 @@ int get_resource_attr_array(struct resource *resource, u_int64_t attr_id, struct return 0; } -int put_resource_attr_array(struct resource *resource, u_int64_t attr_id) -{ - struct resource_attribute_value *attr_value = NULL; - struct array_value *array; - - if (!check_attr_validate(resource, attr_id, DATA_TYPE_ARRAY)) - return -EINVAL; - - attr_value = get_resource_attr_value(resource, attr_id); - if (!attr_value || !attr_value->data) - return -EINVAL; - - array = (struct array_value *)attr_value->data; - if (array) { - array->type = 0; - array->length = 0; - free(array->data); - array->data = NULL; - } - free(attr_value->data); - attr_value->data = NULL; - - return 0; -} - int get_resource_attr_ptr(struct resource *resource, u_int64_t attr_id, void **data) { struct resource_attribute_value *attr_value = NULL; @@ -491,35 +433,110 @@ int get_resource_attr_ptr(struct resource *resource, u_int64_t attr_id, void **d return 0; } -int put_resource_attr_ptr(struct resource *resource, u_int64_t attr_id) +void set_resource_attr_interest(struct resource *resource, u_int64_t interest_mask) { - struct resource_attribute_value *attr_value = NULL; + struct resource_attribute_value *attr_value; + int i; - if (!check_attr_validate(resource, attr_id, DATA_TYPE_PTR)) - return -EINVAL; - - attr_value = get_resource_attr_value(resource, attr_id); - if (!attr_value || !attr_value->data) - return -EINVAL; + if (!resource) + return; - free(attr_value->data); - attr_value->data = NULL; + for (i = 0; i < resource->num_attrs; i++) { + if (!(resource->attrs[i].id & interest_mask)) + continue; - return 0; -} + attr_value = get_resource_attr_value(resource, resource->attrs[i].id); + if (!attr_value) { + _E("failed to get attribute value: resource: %s, attribute: %s", + resource->name, resource->attrs[i].name); + return; + } -void set_resource_attr_interest(struct resource *resource, u_int64_t interest_mask) -{ - if (!resource) - return; + /* + * In resource monitor, each resource has a lot of attributes, but + * only updated attributes are selected by clients on demand. So, + * instead of allocating memory at the resource creation, allocate + * at the set interest. + */ + if (!attr_value->data) { + switch (attr_value->type) { + case DATA_TYPE_INT: + attr_value->data = calloc(1, sizeof(int32_t)); + break; + case DATA_TYPE_INT64: + attr_value->data = calloc(1, sizeof(int64_t)); + break; + case DATA_TYPE_UINT: + attr_value->data = calloc(1, sizeof(u_int32_t)); + break; + case DATA_TYPE_UINT64: + attr_value->data = calloc(1, sizeof(u_int64_t)); + break; + case DATA_TYPE_DOUBLE: + attr_value->data = calloc(1, sizeof(double)); + break; + case DATA_TYPE_STRING: + attr_value->data = calloc(BUFF_MAX, sizeof(char)); + break; + case DATA_TYPE_ARRAY: + attr_value->data = calloc(1, sizeof(struct array_value)); + break; + default: + _E("Not supported data type: %d", attr_value->type); + return; + } + } + } resource->attr_interest |= interest_mask; } void unset_resource_attr_interest(struct resource *resource, u_int64_t interest_mask) { + struct resource_attribute_value *attr_value; + int i; + if (!resource) return; + for (i = 0; i < resource->num_attrs; i++) { + if (!(resource->attrs[i].id & interest_mask)) + continue; + + attr_value = get_resource_attr_value(resource, resource->attrs[i].id); + if (!attr_value) { + _E("failed to get attribute value: resource: %s, attribute: %s", + resource->name, resource->attrs[i].name); + return; + } + + if (attr_value->data) { + switch (attr_value->type) { + case DATA_TYPE_ARRAY: + { + struct array_value *array = attr_value->data; + + if (array->data) { + free(array->data); + array->data = NULL; + } + /* fall through */ + } + case DATA_TYPE_INT: + case DATA_TYPE_INT64: + case DATA_TYPE_UINT: + case DATA_TYPE_UINT64: + case DATA_TYPE_DOUBLE: + case DATA_TYPE_STRING: + free(attr_value->data); + attr_value->data = NULL; + break; + default: + _E("Not supported data type: %d", attr_value->type); + return; + } + } + } + resource->attr_interest &= ~interest_mask; } -- 2.7.4