From 9e34d4f3175666353518f786811a7d5ce40c756e Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Tue, 29 Mar 2022 14:24:47 +0900 Subject: [PATCH 01/16] monitor: Change delimiter for request/response tokenizing Since JSON format use character ':' as its internal representation, delimiter of API tokenizing is change into '$'. Change-Id: I0705eeb4a860cd279e9ee7b1ab62db3318786fc6 Signed-off-by: Dongwoo Lee --- lib/tmonitor/tmonitor.c | 58 +++++++++++++++++++++---------------------- src/monitor/request-handler.c | 50 ++++++++++++++++++------------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/lib/tmonitor/tmonitor.c b/lib/tmonitor/tmonitor.c index d671adf..0d2aacc 100644 --- a/lib/tmonitor/tmonitor.c +++ b/lib/tmonitor/tmonitor.c @@ -99,7 +99,7 @@ static int handle_resource_attr(int request, int id, int resource_id, u_int64_t int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64, request, resource_id, attr_mask); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -114,7 +114,7 @@ static int handle_resource_attr(int request, int id, int resource_id, u_int64_t } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != request) { @@ -197,7 +197,7 @@ int tmonitor_get_resource_count(int id, int resource_type) int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d", + buffer_len = sprintf(buffer, "%d$%d", REQUEST_GET_RESOURCE_COUNT, resource_type); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -212,7 +212,7 @@ int tmonitor_get_resource_count(int id, int resource_type) } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != REQUEST_GET_RESOURCE_COUNT) { @@ -231,7 +231,7 @@ int tmonitor_create_resource(int id, int resource_type) int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d", REQUEST_CREATE_RESOURCE, resource_type); + 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; @@ -245,7 +245,7 @@ int tmonitor_create_resource(int id, int resource_type) } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != REQUEST_CREATE_RESOURCE) { @@ -264,7 +264,7 @@ int tmonitor_delete_resource(int id, int resource_id) int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d", REQUEST_DELETE_RESOURCE, resource_id); + buffer_len = sprintf(buffer, "%d$%d", REQUEST_DELETE_RESOURCE, resource_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer for create resource"); return -EIO; @@ -278,7 +278,7 @@ int tmonitor_delete_resource(int id, int resource_id) } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != REQUEST_DELETE_RESOURCE) { @@ -297,7 +297,7 @@ int tmonitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int v int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64":%d", + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64"$%d", REQUEST_SET_RESOURCE_CTRL, resource_id, ctrl_id, value); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -312,7 +312,7 @@ int tmonitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int v } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != REQUEST_SET_RESOURCE_CTRL) { @@ -343,7 +343,7 @@ bool tmonitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64"", + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64"", REQUEST_IS_RESOURCE_ATTR_SUPPORTED, resource_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -358,7 +358,7 @@ bool tmonitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != REQUEST_IS_RESOURCE_ATTR_SUPPORTED) { @@ -391,7 +391,7 @@ int tmonitor_update(int id) } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != REQUEST_UPDATE_RESOURCE_ALL) { @@ -410,7 +410,7 @@ int tmonitor_update_resource(int id, int resource_id) int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d", REQUEST_UPDATE_RESOURCE, resource_id); + 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; @@ -424,7 +424,7 @@ int tmonitor_update_resource(int id, int resource_id) } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d", &response_req, &ret) < 2) + if (sscanf(buffer, "%d$%d", &response_req, &ret) < 2) return -EINVAL; if (response_req != REQUEST_UPDATE_RESOURCE) { @@ -443,7 +443,7 @@ int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t * int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + 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"); @@ -458,7 +458,7 @@ int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t * } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d:%d", &response_req, value, &ret) < 3) + if (sscanf(buffer, "%d$%d$%d", &response_req, value, &ret) < 3) return -EINVAL; if (response_req != REQUEST_GET_VALUE_INT) { @@ -477,7 +477,7 @@ int tmonitor_get_value_int64(int id, int resource_id, u_int64_t attr_id, int64_t int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_INT64, resource_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -492,7 +492,7 @@ int tmonitor_get_value_int64(int id, int resource_id, u_int64_t attr_id, int64_t } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%"PRId64":%d", &response_req, value, &ret) < 3) + if (sscanf(buffer, "%d$%"PRId64"$%d", &response_req, value, &ret) < 3) return -EINVAL; if (response_req != REQUEST_GET_VALUE_INT64) { @@ -511,7 +511,7 @@ int tmonitor_get_value_uint(int id, int resource_id, u_int64_t attr_id, u_int32_ int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_UINT, resource_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -526,7 +526,7 @@ int tmonitor_get_value_uint(int id, int resource_id, u_int64_t attr_id, u_int32_ } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d:%d", &response_req, value, &ret) < 3) + if (sscanf(buffer, "%d$%d$%d", &response_req, value, &ret) < 3) return -EINVAL; if (response_req != REQUEST_GET_VALUE_UINT) { @@ -545,7 +545,7 @@ int tmonitor_get_value_uint64(int id, int resource_id, u_int64_t attr_id, u_int6 int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_UINT64, resource_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -560,7 +560,7 @@ int tmonitor_get_value_uint64(int id, int resource_id, u_int64_t attr_id, u_int6 } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%"PRIu64":%d", &response_req, value, &ret) < 3) + if (sscanf(buffer, "%d$%"PRIu64"$%d", &response_req, value, &ret) < 3) return -EINVAL; if (response_req != REQUEST_GET_VALUE_UINT64) { @@ -579,7 +579,7 @@ int tmonitor_get_value_double(int id, int resource_id, u_int64_t attr_id, double int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_DOUBLE, resource_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -594,7 +594,7 @@ int tmonitor_get_value_double(int id, int resource_id, u_int64_t attr_id, double } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%lf:%d", &response_req, value, &ret) < 3) + if (sscanf(buffer, "%d$%lf$%d", &response_req, value, &ret) < 3) return -EINVAL; if (response_req != REQUEST_GET_VALUE_DOUBLE) { @@ -613,7 +613,7 @@ int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr_id, char * int response_req; int ret; - buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + buffer_len = sprintf(buffer, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_STRING, resource_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -628,7 +628,7 @@ int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr_id, char * } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%[^:]:%d", &response_req, value, &ret) < 3) + if (sscanf(buffer, "%d$%[^$]$%d", &response_req, value, &ret) < 3) return -EINVAL; if (response_req != REQUEST_GET_VALUE_STRING) { @@ -658,7 +658,7 @@ tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void ** return -ENOMEM; } - buffer_len = snprintf(buffer, ARRAY_BUFF_MAX, "%d:%d:%"PRIu64, + buffer_len = snprintf(buffer, ARRAY_BUFF_MAX, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_ARRAY, res_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -675,7 +675,7 @@ tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void ** } buffer[buffer_len] = '\0'; - if (sscanf(buffer, "%d:%d|%d|%[^:]:%d", &response_req, + if (sscanf(buffer, "%d$%d|%d|%[^$]$%d", &response_req, &array_type, &array_len, array_str, &ret) < 5) { ret = -EINVAL; goto out_free; diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 9d8a224..3cb97ca 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -180,7 +180,7 @@ static int handle_request_set_resource_attr(struct request_client *client, char * Format of REQUEST_SET_RESOURCE_ATTR and REQUEST_UNSET_RESOURCE_ATTR args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &interest_masks) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &interest_masks) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -214,7 +214,7 @@ static int handle_request_is_resource_attr_supported(struct request_client *clie * Format of REQUEST_IS_RESOURCE_ATTR_SUPPORTED args: * - */ - if (sscanf(args, "%d:%"PRIu64"", &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64"", &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -237,7 +237,7 @@ static int handle_request_set_resource_ctrl(struct request_client *client, char * Format of REQUEST_SET_RESOURCE_CTRL args: * - */ - if (sscanf(args, "%d:%"PRIu64":%d", &resource_id, &ctrl_id, &value) < 3) + if (sscanf(args, "%d$%"PRIu64"$%d", &resource_id, &ctrl_id, &value) < 3) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -260,7 +260,7 @@ static int handle_request_get_value_int(struct request_client *client, char *arg * Format of REQUEST_GET_VALUE_INT args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -283,7 +283,7 @@ static int handle_request_get_value_int64(struct request_client *client, char *a * Format of REQUEST_GET_VALUE_INT64 args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -307,7 +307,7 @@ handle_request_get_value_uint(struct request_client *client, char *args, u_int32 * Format of REQUEST_GET_VALUE_UINT args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -331,7 +331,7 @@ handle_request_get_value_uint64(struct request_client *client, char *args, u_int * Format of REQUEST_GET_VALUE_UINT64 args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -354,7 +354,7 @@ static int handle_request_get_value_double(struct request_client *client, char * * Format of REQUEST_GET_VALUE_DOUBLE args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -377,7 +377,7 @@ static int handle_request_get_value_string(struct request_client *client, char * * Format of REQUEST_GET_VALUE_INT args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -401,7 +401,7 @@ handle_request_get_value_array(struct request_client *client, char *args, struct * Format of REQUEST_GET_VALUE_ARRAY args: * - */ - if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; res = get_resource_by_id(client, resource_id); @@ -415,7 +415,7 @@ static int split_request_type_and_args(char *buffer, char **args) { char *request_type_str; - request_type_str = strsep(&buffer, ":"); + request_type_str = strsep(&buffer, "$"); *args = buffer; @@ -451,7 +451,7 @@ static int handle_request(struct request_client *client, char *request) * Format of response * - */ - ADD_RESPONSE(response, buffer_len, "%d:", request_type); + ADD_RESPONSE(response, buffer_len, "%d$", request_type); switch (request_type) { case REQUEST_CREATE_RESOURCE: @@ -505,7 +505,7 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _D("failed to get value"); - ADD_RESPONSE(response, buffer_len, "%d:", value); + ADD_RESPONSE(response, buffer_len, "%d$", value); } break; case REQUEST_GET_VALUE_INT64: @@ -516,7 +516,7 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _D("failed to get value"); - ADD_RESPONSE(response, buffer_len, "%"PRId64":", value); + ADD_RESPONSE(response, buffer_len, "%"PRId64"$", value); } break; case REQUEST_GET_VALUE_UINT: @@ -527,7 +527,7 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _D("failed to get value"); - ADD_RESPONSE(response, buffer_len, "%u:", value); + ADD_RESPONSE(response, buffer_len, "%u$", value); } break; case REQUEST_GET_VALUE_UINT64: @@ -538,7 +538,7 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _D("failed to get value"); - ADD_RESPONSE(response, buffer_len, "%"PRIu64":", value); + ADD_RESPONSE(response, buffer_len, "%"PRIu64"$", value); } break; case REQUEST_GET_VALUE_DOUBLE: @@ -549,7 +549,7 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _D("failed to get value"); - ADD_RESPONSE(response, buffer_len, "%lf:", value); + ADD_RESPONSE(response, buffer_len, "%lf$", value); } break; case REQUEST_GET_VALUE_STRING: @@ -560,7 +560,7 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _D("failed to get value"); - ADD_RESPONSE(response, buffer_len, "%s:", value); + ADD_RESPONSE(response, buffer_len, "%s$", value); } break; case REQUEST_GET_VALUE_ARRAY: @@ -573,7 +573,7 @@ static int handle_request(struct request_client *client, char *request) _D("failed to get value"); if (array->length == 0) { - ADD_RESPONSE(response, buffer_len, "%d|%d|:", + ADD_RESPONSE(response, buffer_len, "%d|%d|$", array->type, array->length); break; } @@ -585,42 +585,42 @@ static int handle_request(struct request_client *client, char *request) for (i = 0; i < array->length - 1; i++) ADD_RESPONSE(response, buffer_len, "%d,", ((int32_t *)array->data)[i]); - ADD_RESPONSE(response, buffer_len, "%d:", + ADD_RESPONSE(response, buffer_len, "%d$", ((int32_t *)array->data)[i]); break; case DATA_TYPE_INT64: for (i = 0; i < array->length - 1; i++) ADD_RESPONSE(response, buffer_len, "%"PRId64",", ((int64_t *)array->data)[i]); - ADD_RESPONSE(response, buffer_len, "%"PRId64":", + ADD_RESPONSE(response, buffer_len, "%"PRId64"$", ((int64_t *)array->data)[i]); break; case DATA_TYPE_UINT: for (i = 0; i < array->length - 1; i++) ADD_RESPONSE(response, buffer_len, "%u,", ((u_int32_t *)array->data)[i]); - ADD_RESPONSE(response, buffer_len, "%u:", + ADD_RESPONSE(response, buffer_len, "%u$", ((u_int32_t *)array->data)[i]); break; case DATA_TYPE_UINT64: for (i = 0; i < array->length - 1; i++) ADD_RESPONSE(response, buffer_len, "%"PRIu64",", ((u_int64_t *)array->data)[i]); - ADD_RESPONSE(response, buffer_len, "%"PRIu64":", + ADD_RESPONSE(response, buffer_len, "%"PRIu64"$", ((u_int64_t *)array->data)[i]); break; case DATA_TYPE_DOUBLE: for (i = 0; i < array->length - 1; i++) ADD_RESPONSE(response, buffer_len, "%lf,", ((double *)array->data)[i]); - ADD_RESPONSE(response, buffer_len, "%lf:", + ADD_RESPONSE(response, buffer_len, "%lf$", ((double *)array->data)[i]); break; case DATA_TYPE_STRING: for (i = 0; i < array->length - 1; i++) ADD_RESPONSE(response, buffer_len, "%s,", ((char **)array->data)[i]); - ADD_RESPONSE(response, buffer_len, "%s:", + ADD_RESPONSE(response, buffer_len, "%s$", ((char **)array->data)[i]); break; default: -- 2.7.4 From 92e445c6da8b6e97e24a18f1a2e817048e17c9fc Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Tue, 29 Mar 2022 11:41:54 +0900 Subject: [PATCH 02/16] util: resource: Add JSON format support To extend use of monitor resource, now all attributes in resource can be retrieved as JSON type format at once with new api below: - tmonitor_get_value_json: get a attribute of resource as json format - tmonitor_get_resource_json: get all attributes of resource as json format Change-Id: I14b1f5e2474d101ff7149a3377b2ebc1890223c8 Signed-off-by: Dongwoo Lee --- include/util/request.h | 4 +- include/util/resource.h | 3 + lib/tmonitor/tmonitor.c | 83 +++++++++++++++++- lib/tmonitor/tmonitor.h | 11 +++ src/monitor/request-handler.c | 68 ++++++++++++++- src/util/resource.c | 193 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 354 insertions(+), 8 deletions(-) diff --git a/include/util/request.h b/include/util/request.h index beefa42..fcee614 100644 --- a/include/util/request.h +++ b/include/util/request.h @@ -19,7 +19,7 @@ #define __REQUEST_H__ #define GENERIC_BUFF_MAX (1024) -#define ARRAY_BUFF_MAX (64 * 1024) +#define HUGE_BUFF_MAX (64 * 1024) /* * request format * REQUEST_TYPE:REQUEST_CONTENT(if required) @@ -35,6 +35,8 @@ enum { REQUEST_SET_RESOURCE_ATTR, REQUEST_UNSET_RESOURCE_ATTR, REQUEST_IS_RESOURCE_ATTR_SUPPORTED, + REQUEST_GET_RESOURCE_JSON, + REQUEST_GET_VALUE_JSON, REQUEST_GET_VALUE_INT, REQUEST_GET_VALUE_INT64, REQUEST_GET_VALUE_UINT, diff --git a/include/util/resource.h b/include/util/resource.h index 18ce421..71d756f 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -179,6 +179,9 @@ resource_attr_supported_always(const struct resource *resource, return true; } +int get_resource_attrs_json(struct resource *resource, char **json_string); + +int get_resource_attr_json(struct resource *resource, u_int64_t attr_id, char **json_string); 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); diff --git a/lib/tmonitor/tmonitor.c b/lib/tmonitor/tmonitor.c index 0d2aacc..bfd9653 100644 --- a/lib/tmonitor/tmonitor.c +++ b/lib/tmonitor/tmonitor.c @@ -435,6 +435,81 @@ int tmonitor_update_resource(int id, int resource_id) return ret; } + +static int tmonitor_get_json(int id, char *json_string, int request_type, ...) +{ + int buffer_len, response_req, ret, resource_id; + u_int64_t attr_id; + char *buffer; + va_list args; + + buffer = malloc(HUGE_BUFF_MAX + 1); + if (!buffer) + return -ENOMEM; + + va_start(args, request_type); + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + resource_id = va_arg(args, int); + buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d$%d", + request_type, resource_id); + break; + case REQUEST_GET_VALUE_JSON: + resource_id = va_arg(args, int); + attr_id = va_arg(args, u_int64_t); + buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d$%d$%"PRIu64, + request_type, resource_id, attr_id); + break; + default: + va_end(args); + free(buffer); + return -EINVAL; + } + va_end(args); + + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer"); + free(buffer); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, HUGE_BUFF_MAX, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + free(buffer); + return -EIO; + } + buffer[buffer_len] = '\0'; + + if (sscanf(buffer, "%d$%[^$]$%d", &response_req, json_string, &ret) < 3) { + free(buffer); + return -EINVAL; + } + + if (response_req != request_type) { + _E("[libpass] wrong response"); + free(buffer); + return -EINVAL; + } + + free(buffer); + + return ret; +} + +EXPORT +int tmonitor_get_resource_json(int id, int resource_id, char *json_string) +{ + return tmonitor_get_json(id, json_string, REQUEST_GET_RESOURCE_JSON, resource_id); +} + +EXPORT +int tmonitor_get_value_json(int id, int resource_id, u_int64_t attr_id, char *json_string) +{ + return tmonitor_get_json(id, json_string, REQUEST_GET_VALUE_JSON, resource_id, attr_id); +} + EXPORT int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t *value) { @@ -648,17 +723,17 @@ tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void ** int response_req; int ret, i; - buffer = malloc(ARRAY_BUFF_MAX + 1); + buffer = malloc(HUGE_BUFF_MAX + 1); if (!buffer) return -ENOMEM; - array_str = malloc(ARRAY_BUFF_MAX); + array_str = malloc(HUGE_BUFF_MAX); if (!array_str) { free(buffer); return -ENOMEM; } - buffer_len = snprintf(buffer, ARRAY_BUFF_MAX, "%d$%d$%"PRIu64, + buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d$%d$%"PRIu64, REQUEST_GET_VALUE_ARRAY, res_id, attr_id); if (send(id, buffer, buffer_len, 0) < 0) { _E("[libpass] error occurred while sending buffer"); @@ -667,7 +742,7 @@ tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void ** } /* wait for response */ - buffer_len = recv(id, buffer, ARRAY_BUFF_MAX, 0); + buffer_len = recv(id, buffer, HUGE_BUFF_MAX, 0); if (buffer_len <= 0) { _E("[libpass] socket disconnected"); ret = -EIO; diff --git a/lib/tmonitor/tmonitor.h b/lib/tmonitor/tmonitor.h index f3c9688..cee45ea 100644 --- a/lib/tmonitor/tmonitor.h +++ b/lib/tmonitor/tmonitor.h @@ -220,6 +220,15 @@ int tmonitor_update(int id); int tmonitor_update_resource(int id, int resource_id); /** + * @brief Get all value in interesting attributes of resource by the JSON string format + * @param[in] Tizen monitor id + * @param[in] Resource id + * @param[out] JSON type string for resource + * @return @c positive integer as resource count on success, otherwise a negative error value + */ +int tmonitor_get_resource_json(int id, int resource_id, char *json_string); + +/** * @brief Get [int/int64/uint/uint64/double/string] value of resource attribute * @param[in] Tizen monitor id * @param[in] Resource id @@ -227,6 +236,8 @@ int tmonitor_update_resource(int id, int resource_id); * @param[out] Value retrieved from resource attribute * @return @ 0 on success, otherwise a negative error value */ + +int tmonitor_get_value_json(int id, int resource_id, u_int64_t attr, char *json_string); int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr, int32_t *value); int tmonitor_get_value_int64(int id, int resource_id, u_int64_t attr, int64_t *value); int tmonitor_get_value_uint(int id, int resource_id, u_int64_t attr, u_int32_t *value); diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 3cb97ca..3bbea40 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -247,6 +247,49 @@ static int handle_request_set_resource_ctrl(struct request_client *client, char return set_resource_control(res, ctrl_id, (void *)(intptr_t)value); } +static int +handle_request_get_json(struct request_client *client, char *args, + int request_type, char **json_string) +{ + struct resource *res; + u_int64_t attr_id; + int resource_id; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_GET_RESOURCE_JSON args: + * - + * Format of REQUEST_GET_VALUE_JSON args: + * - : + */ + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + resource_id = atoi(args); + break; + case REQUEST_GET_VALUE_JSON: + if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) + return -EINVAL; + break; + default: + return -EINVAL; + } + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + return get_resource_attrs_json(res, json_string); + case REQUEST_GET_VALUE_JSON: + return get_resource_attr_json(res, attr_id, json_string); + default: + return -EINVAL; + } +} + static int handle_request_get_value_int(struct request_client *client, char *args, int32_t *value) { struct resource *res; @@ -438,10 +481,15 @@ static int handle_request(struct request_client *client, char *request) request_type = split_request_type_and_args(request, &args); - if (request_type == REQUEST_GET_VALUE_ARRAY) - buffer_len = ARRAY_BUFF_MAX + 1; - else + switch (request_type) { + case REQUEST_GET_RESOURCE_JSON: + case REQUEST_GET_VALUE_JSON: + case REQUEST_GET_VALUE_ARRAY: + buffer_len = HUGE_BUFF_MAX + 1; + break; + default: buffer_len = GENERIC_BUFF_MAX + 1; + } response_entry = response = malloc(buffer_len); if (!response_entry) @@ -497,6 +545,20 @@ static int handle_request(struct request_client *client, char *request) if (ret < 0) _E("failed to check whether attr is supported or not"); break; + case REQUEST_GET_RESOURCE_JSON: + case REQUEST_GET_VALUE_JSON: + { + char *json_string; + + ret = handle_request_get_json(client, args, request_type, &json_string); + if (ret < 0) + _E("failed to get resource JSON string"); + + ADD_RESPONSE(response, buffer_len, "%s$", json_string); + + free(json_string); + } + break; case REQUEST_GET_VALUE_INT: { int32_t value; diff --git a/src/util/resource.c b/src/util/resource.c index 5149726..aefe3cc 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -341,6 +342,198 @@ static bool check_attr_validate(struct resource *resource, u_int64_t attr_id, in return true; } +static json_object *_get_resource_attr_json(const struct resource_attribute *attr, + const struct resource_attribute_value *attr_value) +{ + json_object *jobj_attr, *jobj_attr_name, *jobj_attr_type, *jobj_attr_value, *jobj_temp; + struct array_value *array; + int i; + + switch (attr->type) { + case DATA_TYPE_INT: + jobj_attr_value = json_object_new_int(*((int32_t *)attr_value->data)); + break; + case DATA_TYPE_UINT: + jobj_attr_value = json_object_new_int(*((u_int32_t *)attr_value->data)); + break; + case DATA_TYPE_INT64: + jobj_attr_value = json_object_new_int64(*((int64_t *)attr_value->data)); + break; + case DATA_TYPE_UINT64: + jobj_attr_value = json_object_new_uint64(*((u_int64_t *)attr_value->data)); + break; + case DATA_TYPE_DOUBLE: + jobj_attr_value = json_object_new_double(*((double *)attr_value->data)); + break; + case DATA_TYPE_STRING: + jobj_attr_value = json_object_new_string((char *)attr_value->data); + break; + case DATA_TYPE_ARRAY: + array = attr_value->data; + + jobj_attr_value = json_object_new_array(); + + switch (array->type) { + case DATA_TYPE_INT: + for (i = 0; i < array->length; i++) { + int32_t *item = array->data; + + jobj_temp = json_object_new_int(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_UINT: + for (i = 0; i < array->length; i++) { + u_int32_t *item = array->data; + + jobj_temp = json_object_new_int(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_INT64: + for (i = 0; i < array->length; i++) { + int64_t *item = array->data; + + jobj_temp = json_object_new_int64(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_UINT64: + for (i = 0; i < array->length; i++) { + u_int64_t *item = array->data; + + jobj_temp = json_object_new_uint64(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_DOUBLE: + for (i = 0; i < array->length; i++) { + double *item = array->data; + + jobj_temp = json_object_new_double(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + case DATA_TYPE_STRING: + for (i = 0; i < array->length; i++) { + char **item = array->data; + + jobj_temp = json_object_new_string(item[i]); + json_object_array_add(jobj_attr_value, jobj_temp); + } + break; + default: + _E("wrong attribute data type in array\n"); + json_object_put(jobj_attr_value); + jobj_attr_value = json_object_new_null(); + } + break; + default: + _E("wrong attribute data type\n"); + jobj_attr_value = json_object_new_null(); + } + jobj_attr = json_object_new_object(); + + jobj_attr_name = json_object_new_string(attr->name); + /* + * Since actually JSON format has no data type limitation itself, in many + * cases except converting JSON into json-c, type is not required. So, + * for the case of converting JSON generated here to json-c object again + * json_type is stored in each attributes. + */ + jobj_attr_type = json_object_new_int(json_object_get_type(jobj_attr_value)); + + json_object_object_add(jobj_attr, "name", jobj_attr_name); + json_object_object_add(jobj_attr, "json_type", jobj_attr_type); + json_object_object_add(jobj_attr, "value", jobj_attr_value); + + return jobj_attr; +} + +static void _put_resource_attr_json(json_object *jobj_attr) +{ + json_object *jobj_attr_value; + + json_object_object_del(jobj_attr, "name"); + json_object_object_del(jobj_attr, "json_type"); + + if (json_object_object_get_ex(jobj_attr, "value", &jobj_attr_value) && + json_object_is_type(jobj_attr_value, json_type_array)) + json_object_array_del_idx(jobj_attr_value, 0, + json_object_array_length(jobj_attr_value)); + + json_object_object_del(jobj_attr, "value"); +} + +int get_resource_attrs_json(struct resource *resource, char **json_string) +{ + json_object *jobj_root, *jobj_res_name, *jobj_res_type, *jobj_res_attrs, *jobj_attr; + const struct resource_attribute *attr; + const struct resource_attribute_value *attr_value; + int i; + + if (!resource || !resource->type) + return -EINVAL; + + jobj_root = json_object_new_object(); + + jobj_res_name = json_object_new_string(resource->name); + jobj_res_type = json_object_new_int(resource->type); + jobj_res_attrs = json_object_new_array(); + + for (i = 0; i < resource->num_attrs; i++) { + if (!(resource->attrs[i].id & resource->attr_interest)) + continue; + + attr = &resource->attrs[i]; + attr_value = &resource->attrs_value[i]; + + jobj_attr = _get_resource_attr_json(attr, attr_value); + + json_object_array_add(jobj_res_attrs, jobj_attr); + } + + json_object_object_add(jobj_root, "res_name", jobj_res_name); + json_object_object_add(jobj_root, "res_type", jobj_res_type); + json_object_object_add(jobj_root, "res_attrs", jobj_res_attrs); + + *json_string = strdup(json_object_to_json_string(jobj_root)); + + for (i = 0; i < json_object_array_length(jobj_res_attrs); i++) { + jobj_attr = json_object_array_get_idx(jobj_res_attrs, i); + _put_resource_attr_json(jobj_attr); + } + json_object_array_del_idx(jobj_res_attrs, 0, json_object_array_length(jobj_res_attrs)); + + json_object_object_del(jobj_root, "res_attrs"); + json_object_object_del(jobj_root, "res_type"); + json_object_object_del(jobj_root, "res_name"); + json_object_put(jobj_root); + + return 0; +} + +int get_resource_attr_json(struct resource *resource, u_int64_t attr_id, char **json_string) +{ + const struct resource_attribute *attr; + const struct resource_attribute_value *attr_value; + json_object *jobj_attr; + + attr = get_resource_attr(resource, attr_id); + attr_value = get_resource_attr_value(resource, attr_id); + + if (!attr || !attr_value) + return -EINVAL; + + jobj_attr = _get_resource_attr_json(attr, attr_value); + + *json_string = strdup(json_object_to_json_string(jobj_attr)); + + _put_resource_attr_json(jobj_attr); + + return 0; +} + int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data) { struct resource_attribute_value *attr_value = NULL; -- 2.7.4 From 184d1f1812428fe302486094110868205fe7ac92 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 1 Apr 2022 14:34:13 +0900 Subject: [PATCH 03/16] lib: resource-monitor: Rename to libpass-resource-monitor from tmonitor Change-Id: If008aa6ab64b04226f97709ea48e13e459cc9a61 Signed-off-by: Chanwoo Choi --- lib/CMakeLists.txt | 13 +-- .../resource-monitor.c} | 103 +++++++++++---------- .../resource-monitor.h} | 88 +++++++++--------- ....manifest => libpass-resource-monitor.manifest} | 0 ...ibpass.pc.in => libpass-resource-monitor.pc.in} | 4 +- packaging/pass.spec | 22 ++--- src/resource/resource-battery.c | 2 +- src/resource/resource-bus.c | 2 +- src/resource/resource-cpu.c | 2 +- src/resource/resource-display.c | 2 +- src/resource/resource-gpu.c | 2 +- src/resource/resource-memory.c | 2 +- src/resource/resource-process-group.c | 2 +- src/resource/resource-process.c | 2 +- src/resource/resource-system.c | 2 +- 15 files changed, 125 insertions(+), 123 deletions(-) rename lib/{tmonitor/tmonitor.c => resource-monitor/resource-monitor.c} (80%) rename lib/{tmonitor/tmonitor.h => resource-monitor/resource-monitor.h} (70%) rename packaging/{libpass.manifest => libpass-resource-monitor.manifest} (100%) rename packaging/{libpass.pc.in => libpass-resource-monitor.pc.in} (81%) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 4f6a41d..78a3b9c 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,6 +1,7 @@ -PROJECT(libpass C) +PROJECT(libpass-resource-monitor C) -SET(NAME pass) +SET(NAME_PASS pass) +SET(NAME_PASS_RESOURCE_MONITOR pass-resource-monitor) SET(VERSION_MAJOR 0) SET(VERSION "${VERSION_MAJOR}.1.0") @@ -30,20 +31,20 @@ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functi SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt") SET(CMAKE_EXE_LINKER_FLAGS "-pie") -SET(SRCS ./tmonitor/tmonitor.c) +SET(SRCS ./resource-monitor/resource-monitor.c) ADD_LIBRARY( ${PROJECT_NAME} SHARED ${SRCS}) TARGET_LINK_LIBRARIES( ${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl -Wl,-z,nodelete,--no-undefined) SET_TARGET_PROPERTIES( ${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) SET_TARGET_PROPERTIES( ${PROJECT_NAME} PROPERTIES VERSION ${VERSION}) -SET_TARGET_PROPERTIES( ${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${NAME}) +SET_TARGET_PROPERTIES( ${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${NAME_PASS_RESOURCE_MONITOR}) CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/packaging/${PROJECT_NAME}.pc.in ${CMAKE_SOURCE_DIR}/packaging/${PROJECT_NAME}.pc @ONLY) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIBDIR}) -INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tmonitor/ - DESTINATION ${INCLUDEDIR}/${NAME}/ +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/resource-monitor/ + DESTINATION ${INCLUDEDIR}/${NAME_PASS}/ FILES_MATCHING PATTERN "*.h") INSTALL(FILES ${CMAKE_SOURCE_DIR}/packaging/${PROJECT_NAME}.pc DESTINATION ${LIBDIR}/pkgconfig) diff --git a/lib/tmonitor/tmonitor.c b/lib/resource-monitor/resource-monitor.c similarity index 80% rename from lib/tmonitor/tmonitor.c rename to lib/resource-monitor/resource-monitor.c index bfd9653..af25357 100644 --- a/lib/tmonitor/tmonitor.c +++ b/lib/resource-monitor/resource-monitor.c @@ -1,5 +1,5 @@ /* - * PASS (Power Aware System Service) - Tizen Monitor Library + * PASS (Power Aware System Service) - Resource Monitor Library * * Copyright (c) 2022 Samsung Electronics Co., Ltd. * @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -35,6 +34,8 @@ #include #include +#include "resource-monitor.h" + #define REQUEST_SERVER_IP "127.0.0.1" #define REQUEST_SERVER_PORT 10001 @@ -44,44 +45,44 @@ extern char *program_invocation_name; #define EXPORT __attribute__ ((visibility("default"))) #endif -struct tmonitor_client { +struct pass_resource_monitor_client { int id; int period; int (*func)(void *data, void *user_data); void *user_data; }; -static GList *g_tmonitor_client_head; +static GList *g_pass_resource_monitor_client_head; static GMutex g_mutex; -void add_client_to_list(struct tmonitor_client *client) +void add_client_to_list(struct pass_resource_monitor_client *client) { if (!client) return; g_mutex_lock(&g_mutex); - g_tmonitor_client_head = - g_list_append(g_tmonitor_client_head, (gpointer)client); + g_pass_resource_monitor_client_head = + g_list_append(g_pass_resource_monitor_client_head, (gpointer)client); g_mutex_unlock(&g_mutex); } -void remove_client_from_list(struct tmonitor_client *client) +void remove_client_from_list(struct pass_resource_monitor_client *client) { if (!client) return; g_mutex_lock(&g_mutex); - g_tmonitor_client_head = - g_list_remove(g_tmonitor_client_head, (gpointer)client); + g_pass_resource_monitor_client_head = + g_list_remove(g_pass_resource_monitor_client_head, (gpointer)client); g_mutex_unlock(&g_mutex); } -static struct tmonitor_client *find_client_by_id(int id) +static struct pass_resource_monitor_client *find_client_by_id(int id) { - struct tmonitor_client *client; + struct pass_resource_monitor_client *client; GList *node; - for (node = g_tmonitor_client_head; + for (node = g_pass_resource_monitor_client_head; node != NULL; node = node->next) { client = node->data; @@ -126,13 +127,13 @@ static int handle_resource_attr(int request, int id, int resource_id, u_int64_t } EXPORT -int tmonitor_init(void) +int pass_resource_monitor_init(void) { - struct tmonitor_client *client; + struct pass_resource_monitor_client *client; struct sockaddr_in server_addr; int ret = -EIO; - client = malloc(sizeof(struct tmonitor_client)); + client = malloc(sizeof(struct pass_resource_monitor_client)); if (!client) { _E("[libpass] failed to allocate memory"); return -ENOMEM; @@ -172,9 +173,9 @@ err_out_free: } EXPORT -int tmonitor_exit(int id) +int pass_resource_monitor_exit(int id) { - struct tmonitor_client *client; + struct pass_resource_monitor_client *client; client = find_client_by_id(id); if (!client) { @@ -190,7 +191,7 @@ int tmonitor_exit(int id) } EXPORT -int tmonitor_get_resource_count(int id, int resource_type) +int pass_resource_monitor_get_resource_count(int id, int resource_type) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -224,7 +225,7 @@ int tmonitor_get_resource_count(int id, int resource_type) } EXPORT -int tmonitor_create_resource(int id, int resource_type) +int pass_resource_monitor_create_resource(int id, int resource_type) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -257,7 +258,7 @@ int tmonitor_create_resource(int id, int resource_type) } EXPORT -int tmonitor_delete_resource(int id, int resource_id) +int pass_resource_monitor_delete_resource(int id, int resource_id) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -290,7 +291,7 @@ int tmonitor_delete_resource(int id, int resource_id) } EXPORT -int tmonitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int value) +int pass_resource_monitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int value) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -324,19 +325,19 @@ int tmonitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int v } EXPORT -int tmonitor_set_resource_attr(int id, int resource_id, u_int64_t attr_mask) +int pass_resource_monitor_set_resource_attr(int id, int resource_id, u_int64_t attr_mask) { return handle_resource_attr(REQUEST_SET_RESOURCE_ATTR, id, resource_id, attr_mask); } EXPORT -int tmonitor_unset_resource_attr(int id, int resource_id, u_int64_t attr_mask) +int pass_resource_monitor_unset_resource_attr(int id, int resource_id, u_int64_t attr_mask) { return handle_resource_attr(REQUEST_UNSET_RESOURCE_ATTR, id, resource_id, attr_mask); } EXPORT -bool tmonitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr_id) +bool pass_resource_monitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr_id) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -370,7 +371,7 @@ bool tmonitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr } EXPORT -int tmonitor_update(int id) +int pass_resource_monitor_update(int id) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -403,7 +404,7 @@ int tmonitor_update(int id) } EXPORT -int tmonitor_update_resource(int id, int resource_id) +int pass_resource_monitor_update_resource(int id, int resource_id) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -436,7 +437,7 @@ int tmonitor_update_resource(int id, int resource_id) } -static int tmonitor_get_json(int id, char *json_string, int request_type, ...) +static int pass_resource_monitor_get_json(int id, char *json_string, int request_type, ...) { int buffer_len, response_req, ret, resource_id; u_int64_t attr_id; @@ -499,19 +500,19 @@ static int tmonitor_get_json(int id, char *json_string, int request_type, ...) } EXPORT -int tmonitor_get_resource_json(int id, int resource_id, char *json_string) +int pass_resource_monitor_get_resource_json(int id, int resource_id, char *json_string) { - return tmonitor_get_json(id, json_string, REQUEST_GET_RESOURCE_JSON, resource_id); + return pass_resource_monitor_get_json(id, json_string, REQUEST_GET_RESOURCE_JSON, resource_id); } EXPORT -int tmonitor_get_value_json(int id, int resource_id, u_int64_t attr_id, char *json_string) +int pass_resource_monitor_get_value_json(int id, int resource_id, u_int64_t attr_id, char *json_string) { - return tmonitor_get_json(id, json_string, REQUEST_GET_VALUE_JSON, resource_id, attr_id); + return pass_resource_monitor_get_json(id, json_string, REQUEST_GET_VALUE_JSON, resource_id, attr_id); } EXPORT -int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t *value) +int pass_resource_monitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t *value) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -545,7 +546,7 @@ int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t * } EXPORT -int tmonitor_get_value_int64(int id, int resource_id, u_int64_t attr_id, int64_t *value) +int pass_resource_monitor_get_value_int64(int id, int resource_id, u_int64_t attr_id, int64_t *value) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -579,7 +580,7 @@ int tmonitor_get_value_int64(int id, int resource_id, u_int64_t attr_id, int64_t } EXPORT -int tmonitor_get_value_uint(int id, int resource_id, u_int64_t attr_id, u_int32_t *value) +int pass_resource_monitor_get_value_uint(int id, int resource_id, u_int64_t attr_id, u_int32_t *value) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -613,7 +614,7 @@ int tmonitor_get_value_uint(int id, int resource_id, u_int64_t attr_id, u_int32_ } EXPORT -int tmonitor_get_value_uint64(int id, int resource_id, u_int64_t attr_id, u_int64_t *value) +int pass_resource_monitor_get_value_uint64(int id, int resource_id, u_int64_t attr_id, u_int64_t *value) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -647,7 +648,7 @@ int tmonitor_get_value_uint64(int id, int resource_id, u_int64_t attr_id, u_int6 } EXPORT -int tmonitor_get_value_double(int id, int resource_id, u_int64_t attr_id, double *value) +int pass_resource_monitor_get_value_double(int id, int resource_id, u_int64_t attr_id, double *value) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -681,7 +682,7 @@ int tmonitor_get_value_double(int id, int resource_id, u_int64_t attr_id, double } EXPORT -int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr_id, char *value) +int pass_resource_monitor_get_value_string(int id, int resource_id, u_int64_t attr_id, char *value) { char buffer[GENERIC_BUFF_MAX + 1]; int buffer_len; @@ -715,7 +716,7 @@ int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr_id, char * } static int -tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void **array, int *length) +pass_resource_monitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void **array, int *length) { char *array_item, *array_str, *buffer; int array_len, array_type; @@ -889,37 +890,37 @@ out_free: } EXPORT -int tmonitor_get_array_int(int id, int res_id, u_int64_t attr_id, int32_t **array, int *length) +int pass_resource_monitor_get_array_int(int id, int res_id, u_int64_t attr_id, int32_t **array, int *length) { - return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_INT, (void **)array, length); + return pass_resource_monitor_get_array(id, res_id, attr_id, DATA_TYPE_INT, (void **)array, length); } EXPORT -int tmonitor_get_array_int64(int id, int res_id, u_int64_t attr_id, int64_t **array, int *length) +int pass_resource_monitor_get_array_int64(int id, int res_id, u_int64_t attr_id, int64_t **array, int *length) { - return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_INT64, (void **)array, length); + return pass_resource_monitor_get_array(id, res_id, attr_id, DATA_TYPE_INT64, (void **)array, length); } EXPORT -int tmonitor_get_array_uint(int id, int res_id, u_int64_t attr_id, u_int32_t **array, int *length) +int pass_resource_monitor_get_array_uint(int id, int res_id, u_int64_t attr_id, u_int32_t **array, int *length) { - return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT, (void **)array, length); + return pass_resource_monitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT, (void **)array, length); } EXPORT -int tmonitor_get_array_uint64(int id, int res_id, u_int64_t attr_id, u_int64_t **array, int *length) +int pass_resource_monitor_get_array_uint64(int id, int res_id, u_int64_t attr_id, u_int64_t **array, int *length) { - return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT64, (void **)array, length); + return pass_resource_monitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT64, (void **)array, length); } EXPORT -int tmonitor_get_array_double(int id, int res_id, u_int64_t attr_id, double **array, int *length) +int pass_resource_monitor_get_array_double(int id, int res_id, u_int64_t attr_id, double **array, int *length) { - return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_DOUBLE, (void **)array, length); + return pass_resource_monitor_get_array(id, res_id, attr_id, DATA_TYPE_DOUBLE, (void **)array, length); } EXPORT -int tmonitor_get_array_string(int id, int res_id, u_int64_t attr_id, char ***array, int *length) +int pass_resource_monitor_get_array_string(int id, int res_id, u_int64_t attr_id, char ***array, int *length) { - return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_STRING, (void **)array, length); + return pass_resource_monitor_get_array(id, res_id, attr_id, DATA_TYPE_STRING, (void **)array, length); } diff --git a/lib/tmonitor/tmonitor.h b/lib/resource-monitor/resource-monitor.h similarity index 70% rename from lib/tmonitor/tmonitor.h rename to lib/resource-monitor/resource-monitor.h index cee45ea..3b1b6cb 100644 --- a/lib/tmonitor/tmonitor.h +++ b/lib/resource-monitor/resource-monitor.h @@ -1,5 +1,5 @@ /* - * PASS (Power Aware System Service) - Tizen Monitor Header File + * PASS (Power Aware System Service) - Resource Monitor Header File * * Copyright (c) 2022 Samsung Electronics Co., Ltd. * @@ -16,8 +16,8 @@ * limitations under the License. */ -#ifndef __TMONITOR__ -#define __TMONITOR__ +#ifndef __RESOURCE_MONITOR__ +#define __RESOURCE_MONITOR__ #include #include @@ -131,137 +131,137 @@ extern "C" { #define PROCESS_GROUP_CTRL_ROOT_PID BIT(0) /** - * @brief Initialize the tizen monitor - * @return @c positive integer as tizen monitor id on success, otherwise a negative error value + * @brief Initialize the resource monitor + * @return @c positive integer as resource monitor id on success, otherwise a negative error value */ -int tmonitor_init(void); +int pass_resource_monitor_init(void); /** * @brief Exit the tizem monitor - * @param[in] Id of tizen monitor which be returnted by tmonitor_init + * @param[in] Id of resource monitor which be returnted by pass_resource_monitor_init * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_exit(int id); +int pass_resource_monitor_exit(int id); /** * @brief Get the count of supported resources according to resource type - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource type * @return @c positive integer as resource count on success, otherwise a negative error value */ -int tmonitor_get_resource_count(int id, int resource_type); +int pass_resource_monitor_get_resource_count(int id, int resource_type); /** * @brief Create resource for given resource_type - * @param[in] Tizen monitor id which be returnted by tmonitor_init + * @param[in] Resource monitor id which be returnted by pass_resource_monitor_init * @param[in] Resource type * @return @c positive integer as resource id on success, otherwise a negative error value */ -int tmonitor_create_resource(int id, int resource_type); +int pass_resource_monitor_create_resource(int id, int resource_type); /** * @brief Delete resource of given resource id - * @param[in] Tizen monitor id which be returnted by tmonitor_init + * @param[in] Resource monitor id which be returnted by pass_resource_monitor_init * @param[in] Resource id * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_delete_resource(int id, int resource_id); +int pass_resource_monitor_delete_resource(int id, int resource_id); /** * @brief Set the resource control with value which is diffierential according to resource control id - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @param[in] Resource control id * @param[in] Value for resource control id * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int value); +int pass_resource_monitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int value); /** * @brief Set the interested attributes for monitoring - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @param[in] Attribute mask including the various attributes * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_set_resource_attr(int id, int resource_id, u_int64_t attr_mask); +int pass_resource_monitor_set_resource_attr(int id, int resource_id, u_int64_t attr_mask); /** * @brief Unset the interested attributes for monitoring - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @param[in] Attribute mask including the various attributes * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_unset_resource_attr(int id, int resource_id, u_int64_t attr_mask); +int pass_resource_monitor_unset_resource_attr(int id, int resource_id, u_int64_t attr_mask); /** * @brief Check whether a resouce attribute is supported or not - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @param[in] Resource attribute id * @return @c 0 on success, otherwise a negative error value */ -bool tmonitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr_id); +bool pass_resource_monitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr_id); /** * @brief Update value of the interested attributes for all created resource - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_update(int id); +int pass_resource_monitor_update(int id); /** * @brief Update value of the interested attributes for a resource - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @return @c 0 on success, otherwise a negative error value */ -int tmonitor_update_resource(int id, int resource_id); +int pass_resource_monitor_update_resource(int id, int resource_id); /** * @brief Get all value in interesting attributes of resource by the JSON string format - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @param[out] JSON type string for resource * @return @c positive integer as resource count on success, otherwise a negative error value */ -int tmonitor_get_resource_json(int id, int resource_id, char *json_string); +int pass_resource_monitor_get_resource_json(int id, int resource_id, char *json_string); /** * @brief Get [int/int64/uint/uint64/double/string] value of resource attribute - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @param[in] Resource attribute id * @param[out] Value retrieved from resource attribute * @return @ 0 on success, otherwise a negative error value */ -int tmonitor_get_value_json(int id, int resource_id, u_int64_t attr, char *json_string); -int tmonitor_get_value_int(int id, int resource_id, u_int64_t attr, int32_t *value); -int tmonitor_get_value_int64(int id, int resource_id, u_int64_t attr, int64_t *value); -int tmonitor_get_value_uint(int id, int resource_id, u_int64_t attr, u_int32_t *value); -int tmonitor_get_value_uint64(int id, int resource_id, u_int64_t attr, u_int64_t *value); -int tmonitor_get_value_double(int id, int resource_id, u_int64_t attr, double *value); -int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr, char *value); +int pass_resource_monitor_get_value_json(int id, int resource_id, u_int64_t attr, char *json_string); +int pass_resource_monitor_get_value_int(int id, int resource_id, u_int64_t attr, int32_t *value); +int pass_resource_monitor_get_value_int64(int id, int resource_id, u_int64_t attr, int64_t *value); +int pass_resource_monitor_get_value_uint(int id, int resource_id, u_int64_t attr, u_int32_t *value); +int pass_resource_monitor_get_value_uint64(int id, int resource_id, u_int64_t attr, u_int64_t *value); +int pass_resource_monitor_get_value_double(int id, int resource_id, u_int64_t attr, double *value); +int pass_resource_monitor_get_value_string(int id, int resource_id, u_int64_t attr, char *value); /** * @brief Get [int/int64/uint/uint64/double/string] array of resource attribute - * @param[in] Tizen monitor id + * @param[in] Resource monitor id * @param[in] Resource id * @param[in] Resource attribute id * @param[out] Array retrieved from resource attribute * @param[out] Length of array * @return @ 0 on success, otherwise a negative error value */ -int tmonitor_get_array_int(int id, int res_id, u_int64_t attr, int32_t **array, int *length); -int tmonitor_get_array_int64(int id, int res_id, u_int64_t attr, int64_t **array, int *length); -int tmonitor_get_array_uint(int id, int res_id, u_int64_t attr, u_int32_t **array, int *length); -int tmonitor_get_array_uint64(int id, int res_id, u_int64_t attr, u_int64_t **array, int *length); -int tmonitor_get_array_double(int id, int res_id, u_int64_t attr, double **array, int *length); -int tmonitor_get_array_string(int id, int res_id, u_int64_t attr, char ***array, int *length); +int pass_resource_monitor_get_array_int(int id, int res_id, u_int64_t attr, int32_t **array, int *length); +int pass_resource_monitor_get_array_int64(int id, int res_id, u_int64_t attr, int64_t **array, int *length); +int pass_resource_monitor_get_array_uint(int id, int res_id, u_int64_t attr, u_int32_t **array, int *length); +int pass_resource_monitor_get_array_uint64(int id, int res_id, u_int64_t attr, u_int64_t **array, int *length); +int pass_resource_monitor_get_array_double(int id, int res_id, u_int64_t attr, double **array, int *length); +int pass_resource_monitor_get_array_string(int id, int res_id, u_int64_t attr, char ***array, int *length); #ifdef __cplusplus } #endif -#endif /* __TMONITOR__ */ +#endif /* __RESOURCE_MONITOR__ */ diff --git a/packaging/libpass.manifest b/packaging/libpass-resource-monitor.manifest similarity index 100% rename from packaging/libpass.manifest rename to packaging/libpass-resource-monitor.manifest diff --git a/packaging/libpass.pc.in b/packaging/libpass-resource-monitor.pc.in similarity index 81% rename from packaging/libpass.pc.in rename to packaging/libpass-resource-monitor.pc.in index 0f02466..5320335 100644 --- a/packaging/libpass.pc.in +++ b/packaging/libpass-resource-monitor.pc.in @@ -1,10 +1,10 @@ # Package Information for pkg-config -package_name=pass +package_name=pass-resource-monitor prefix=@PREFIX@ exec_prefix=@EXEC_PREFIX@ libdir=@LIBDIR@ -includedir=/usr/include/${package_name} +includedir=/usr/include/pass Name: ${package_name} Description: ${package_name} library diff --git a/packaging/pass.spec b/packaging/pass.spec index dd933af..a9820c8 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -3,7 +3,7 @@ %define daemon_name pass %define haltest_name pass-haltests %define unittest_name pass-unittest -%define libpass_name libpass +%define libpass_resource_monitor_name libpass-resource-monitor Name: %{daemon_name} Summary: Power Aware System Service @@ -13,7 +13,7 @@ Group: System/Kernel License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Source1: %{name}.manifest -Source2: %{libpass_name}.manifest +Source2: %{libpass_resource_monitor_name}.manifest BuildRequires: cmake BuildRequires: pkgconfig(dlog) @@ -54,20 +54,20 @@ Requires: pass = %{version}-%{release} %description -n %{unittest_name} PASS unit test package with gtest -%package -n %{libpass_name} +%package -n %{libpass_resource_monitor_name} Summary: Tizen Monitor Library package Group: Development/Libraries Requires: pass = %{version}-%{release} -%description -n %{libpass_name} +%description -n %{libpass_resource_monitor_name} Tizen Monitor Library package -%package -n %{libpass_name}-devel +%package -n %{libpass_resource_monitor_name}-devel Summary: Tizen Monitor Headler Files Group: Development/Libraries Requires: pass = %{version}-%{release} -%description -n %{libpass_name}-devel +%description -n %{libpass_resource_monitor_name}-devel Tizen Monitor Headler Files %prep @@ -126,16 +126,16 @@ systemctl daemon-reload %defattr(-,root,root,-) %{_bindir}/pass-unittests -%files -n %{libpass_name} +%files -n %{libpass_resource_monitor_name} %license LICENSE -%manifest %{libpass_name}.manifest +%manifest %{libpass_resource_monitor_name}.manifest %defattr(-,root,root,-) %{_libdir}/*.so* -%files -n %{libpass_name}-devel +%files -n %{libpass_resource_monitor_name}-devel %license LICENSE -%manifest %{libpass_name}.manifest +%manifest %{libpass_resource_monitor_name}.manifest %defattr(-,root,root,-) %{_includedir}/%{name}/*.h -%{_libdir}/pkgconfig/%{libpass_name}.pc +%{_libdir}/pkgconfig/%{libpass_resource_monitor_name}.pc %{_libdir}/*.so* diff --git a/src/resource/resource-battery.c b/src/resource/resource-battery.c index d6e5b53..584fe2f 100644 --- a/src/resource/resource-battery.c +++ b/src/resource/resource-battery.c @@ -28,7 +28,7 @@ #include #include -#include +#include static int battery_get_info(const struct resource *res, const struct resource_attribute *attr, diff --git a/src/resource/resource-bus.c b/src/resource/resource-bus.c index 499fd5a..c7e9ab7 100644 --- a/src/resource/resource-bus.c +++ b/src/resource/resource-bus.c @@ -30,7 +30,7 @@ #include #include -#include +#include struct bus_context { char *device_name; diff --git a/src/resource/resource-cpu.c b/src/resource/resource-cpu.c index 2575ff5..c25a6c9 100644 --- a/src/resource/resource-cpu.c +++ b/src/resource/resource-cpu.c @@ -30,7 +30,7 @@ #include #include -#include +#include struct cpu_context { char *device_name; diff --git a/src/resource/resource-display.c b/src/resource/resource-display.c index 30c8f6c..33b8aee 100644 --- a/src/resource/resource-display.c +++ b/src/resource/resource-display.c @@ -31,7 +31,7 @@ #include #include -#include +#include #define DBUS_ENLIGHTENMENT_NAME "org.enlightenment.wm" #define DBUS_ENLIGHTENMENT_PATH "/org/enlightenment/wm" diff --git a/src/resource/resource-gpu.c b/src/resource/resource-gpu.c index ac232e7..b736650 100644 --- a/src/resource/resource-gpu.c +++ b/src/resource/resource-gpu.c @@ -30,7 +30,7 @@ #include #include -#include +#include struct gpu_context { char *device_name; diff --git a/src/resource/resource-memory.c b/src/resource/resource-memory.c index 7ad1061..f0b8782 100644 --- a/src/resource/resource-memory.c +++ b/src/resource/resource-memory.c @@ -31,7 +31,7 @@ #include #include -#include +#include #define PROC_MEM_INFO_MEM_AVAILABLE "MemAvailable" #define PROC_MEM_INFO_MEM_FREE "MemFree" diff --git a/src/resource/resource-process-group.c b/src/resource/resource-process-group.c index 90dec08..a56636d 100644 --- a/src/resource/resource-process-group.c +++ b/src/resource/resource-process-group.c @@ -21,7 +21,7 @@ #include #include -#include +#include #define PROC_DIR_PATH "/proc/" diff --git a/src/resource/resource-process.c b/src/resource/resource-process.c index 0e050af..5702c10 100644 --- a/src/resource/resource-process.c +++ b/src/resource/resource-process.c @@ -26,7 +26,7 @@ #include #include -#include +#include struct process_context { pid_t tgid; diff --git a/src/resource/resource-system.c b/src/resource/resource-system.c index 8eada2e..6f9f2a8 100644 --- a/src/resource/resource-system.c +++ b/src/resource/resource-system.c @@ -31,7 +31,7 @@ #include #include -#include +#include struct system_resouce_data { struct cpu_stat prev_avg; -- 2.7.4 From 6de823871943d0bb8b0d9e7bed3f187ac150fd2e Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 31 Mar 2022 12:14:56 +0900 Subject: [PATCH 04/16] util: kernel: Make query_taskstats() common kernel utility function To use taskstats in other drivers as well as process driver, query_taskstat() now become common kernel utility function and name is changed as following kernel util naming rules. Change-Id: I64eff1892d908d22a0f8f831949b2c072cc0e68b Signed-off-by: Dongwoo Lee --- include/util/kernel.h | 3 + src/resource/resource-process.c | 164 +--------------------------------------- src/util/kernel.c | 164 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 162 deletions(-) diff --git a/include/util/kernel.h b/include/util/kernel.h index 9846466..5938d9f 100644 --- a/include/util/kernel.h +++ b/include/util/kernel.h @@ -20,6 +20,7 @@ #define __KERNEL_H__ #include +#include #include "common.h" struct cpu_stat { @@ -55,4 +56,6 @@ int kernel_get_memory_total(u_int64_t *val); int kernel_get_process_stat_fields(pid_t pid, char *buffer, int buf_len, char *stat_fields[PROCESS_STAT_FIELD_MAX]); +int kernel_get_process_taskstats(struct taskstats *stats, int cmd_type, pid_t pid); +int kernel_get_thread_group_taskstats(struct taskstats *stats, pid_t tgid, bool get_proc_info); #endif diff --git a/src/resource/resource-process.c b/src/resource/resource-process.c index 5702c10..00fb14c 100644 --- a/src/resource/resource-process.c +++ b/src/resource/resource-process.c @@ -18,9 +18,6 @@ #include #include -#include -#include -#include #include #include @@ -308,163 +305,6 @@ static u_int64_t get_total_cpu_time(void) return total_time; } -static int parse_aggregate_task_stats(struct nlattr *attr, int attr_size, - struct taskstats *stats) -{ - nla_for_each_attr(attr, attr, attr_size, attr_size) { - switch (attr->nla_type) { - case TASKSTATS_TYPE_PID: - case TASKSTATS_TYPE_TGID: - break; - case TASKSTATS_TYPE_STATS: - nla_memcpy(stats, attr, sizeof(struct taskstats)); - break; - default: - return -EINVAL; - } - } - - return 0; -} - -static int parse_task_stats(struct nl_msg *msg, void *arg) -{ - struct genlmsghdr *hdr = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *attr = genlmsg_attrdata(hdr, 0); - int remaining = genlmsg_attrlen(hdr, 0); - int ret; - - nla_for_each_attr(attr, attr, remaining, remaining) { - switch (attr->nla_type) { - case TASKSTATS_TYPE_AGGR_PID: - case TASKSTATS_TYPE_AGGR_TGID: - ret = parse_aggregate_task_stats(nla_data(attr), - nla_len(attr), arg); - if (ret < 0) { - _E("failed to parse netlink message\n"); - return NL_STOP; - } - break; - default: - break; - } - } - return NL_STOP; -} - -static int print_receive_error(struct sockaddr_nl *address, - struct nlmsgerr *error, void *arg) -{ - return NL_STOP; -} - -static int query_taskstats(struct taskstats *stats, int cmd_type, pid_t pid) -{ - struct nl_sock *sock; - struct nl_msg *msg; - struct nl_cb *cb; - int ret; - - sock = nl_socket_alloc(); - if (!sock) - return -ENOMEM; - - ret = genl_connect(sock); - if (ret < 0) - goto err_free_sock; - - ret = genl_ctrl_resolve(sock, TASKSTATS_GENL_NAME); - if (ret < 0) - goto err_genl_close; - - msg = nlmsg_alloc(); - if (!msg) { - ret = -ENOMEM; - goto err_genl_close; - } - - genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ret, 0, 0, TASKSTATS_CMD_GET, TASKSTATS_VERSION); - - ret = nla_put_u32(msg, cmd_type, pid); - if (ret < 0) - goto err_msg_free; - - ret = nl_send_auto_complete(sock, msg); - nlmsg_free(msg); - if (ret < 0) - goto err_genl_close; - - cb = nl_cb_get(nl_cb_alloc(NL_CB_CUSTOM)); - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, &parse_task_stats, stats); - nl_cb_err(cb, NL_CB_CUSTOM, &print_receive_error, NULL); - - ret = nl_recvmsgs(sock, cb); - nl_cb_put(cb); - if (ret < 0) - goto err_genl_close; - - nl_close(sock); - nl_socket_free(sock); - - return 0; - -err_msg_free: - nlmsg_free(msg); -err_genl_close: - nl_close(sock); -err_free_sock: - nl_socket_free(sock); - - return ret; -} - -static int update_taskstats(struct process_context *ctx) -{ - struct taskstats stats, *curr = &ctx->curr; - struct dirent *task_entry; - DIR *task_dir; - char task_dir_path[BUFF_MAX]; - pid_t pid; - int ret; - - memset(curr, 0, sizeof(struct taskstats)); - - sprintf(task_dir_path, "/proc/%d/task/", ctx->tgid); - - task_dir = opendir(task_dir_path); - if (!task_dir) - return -ESRCH; - - while ((task_entry = readdir(task_dir)) != NULL) { - const char *name = task_entry->d_name; - - if (task_entry->d_type != DT_DIR && task_entry->d_type != DT_UNKNOWN) - continue; - - if (name[0] < '0' || name[0] > '9') - continue; - - pid = strtoul(name, NULL, 10); - - ret = query_taskstats(&stats, TASKSTATS_CMD_ATTR_PID, pid); - if (ret < 0) - /* threads can be removed before get taskstats */ - continue; - - curr->ac_utime += stats.ac_utime; - curr->ac_stime += stats.ac_stime; - curr->ac_etime += stats.ac_etime; - curr->virtmem += stats.virtmem; - curr->coremem += stats.coremem; - curr->read_bytes += stats.read_bytes; - curr->write_bytes += stats.write_bytes; - } - - closedir(task_dir); - - return 0; -} - static int process_setup_tgid(const struct resource *res, const struct resource_control *ctrl, const void *data) @@ -488,7 +328,7 @@ static int process_setup_tgid(const struct resource *res, ctx->prev_total_time = get_total_cpu_time(); /* update initial status */ - ret = update_taskstats(ctx); + ret = kernel_get_process_taskstats(&ctx->curr, ctx->tgid, false); if (ret < 0) return ret; @@ -524,7 +364,7 @@ static int process_prepare_update(struct resource *res) memcpy(&ctx->prev, &ctx->curr, sizeof(struct taskstats)); - ret = update_taskstats(ctx); + ret = kernel_get_thread_group_taskstats(&ctx->curr, ctx->tgid, false); if (ret < 0) return ret; diff --git a/src/util/kernel.c b/src/util/kernel.c index 3a9c2d6..653b297 100644 --- a/src/util/kernel.c +++ b/src/util/kernel.c @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include #include @@ -243,3 +246,164 @@ int kernel_get_process_stat_fields(pid_t pid, char *buffer, int buf_len, return 0; } + +static int parse_aggregate_task_stats(struct nlattr *attr, int attr_size, + struct taskstats *stats) +{ + nla_for_each_attr(attr, attr, attr_size, attr_size) { + switch (attr->nla_type) { + case TASKSTATS_TYPE_PID: + case TASKSTATS_TYPE_TGID: + break; + case TASKSTATS_TYPE_STATS: + nla_memcpy(stats, attr, sizeof(struct taskstats)); + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static int parse_task_stats(struct nl_msg *msg, void *arg) +{ + struct genlmsghdr *hdr = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *attr = genlmsg_attrdata(hdr, 0); + int remaining = genlmsg_attrlen(hdr, 0); + int ret; + + nla_for_each_attr(attr, attr, remaining, remaining) { + switch (attr->nla_type) { + case TASKSTATS_TYPE_AGGR_PID: + case TASKSTATS_TYPE_AGGR_TGID: + ret = parse_aggregate_task_stats(nla_data(attr), + nla_len(attr), arg); + if (ret < 0) { + _E("failed to parse netlink message\n"); + return NL_STOP; + } + break; + default: + break; + } + } + return NL_STOP; +} + +static int print_receive_error(struct sockaddr_nl *address, + struct nlmsgerr *error, void *arg) +{ + return NL_STOP; +} + +int kernel_get_process_taskstats(struct taskstats *stats, int cmd_type, pid_t pid) +{ + struct nl_sock *sock; + struct nl_msg *msg; + struct nl_cb *cb; + int ret; + + sock = nl_socket_alloc(); + if (!sock) + return -ENOMEM; + + ret = genl_connect(sock); + if (ret < 0) + goto err_free_sock; + + ret = genl_ctrl_resolve(sock, TASKSTATS_GENL_NAME); + if (ret < 0) + goto err_genl_close; + + msg = nlmsg_alloc(); + if (!msg) { + ret = -ENOMEM; + goto err_genl_close; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ret, 0, 0, TASKSTATS_CMD_GET, TASKSTATS_VERSION); + + ret = nla_put_u32(msg, cmd_type, pid); + if (ret < 0) + goto err_msg_free; + + ret = nl_send_auto_complete(sock, msg); + nlmsg_free(msg); + if (ret < 0) + goto err_genl_close; + + cb = nl_cb_get(nl_cb_alloc(NL_CB_CUSTOM)); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, &parse_task_stats, stats); + nl_cb_err(cb, NL_CB_CUSTOM, &print_receive_error, NULL); + + ret = nl_recvmsgs(sock, cb); + nl_cb_put(cb); + if (ret < 0) + goto err_genl_close; + + nl_close(sock); + nl_socket_free(sock); + + return 0; + +err_msg_free: + nlmsg_free(msg); +err_genl_close: + nl_close(sock); +err_free_sock: + nl_socket_free(sock); + + return ret; +} + +int kernel_get_thread_group_taskstats(struct taskstats *stats, pid_t tgid, bool get_proc_info) +{ + struct taskstats pid_stats; + struct dirent *task_entry; + DIR *task_dir; + char task_dir_path[BUFF_MAX]; + pid_t pid; + int ret; + + ret = kernel_get_process_taskstats(stats, TASKSTATS_CMD_ATTR_TGID, tgid); + if (ret < 0) + return -EINVAL; + + sprintf(task_dir_path, "/proc/%d/task/", tgid); + + task_dir = opendir(task_dir_path); + if (!task_dir) + return -ESRCH; + + while ((task_entry = readdir(task_dir)) != NULL) { + const char *name = task_entry->d_name; + + if (task_entry->d_type != DT_DIR && task_entry->d_type != DT_UNKNOWN) + continue; + + if (name[0] < '0' || name[0] > '9') + continue; + + pid = strtoul(name, NULL, 10); + + ret = kernel_get_process_taskstats(&pid_stats, TASKSTATS_CMD_ATTR_PID, pid); + if (ret < 0) + /* threads can be removed before get taskstats */ + continue; + + if (get_proc_info && tgid == pid_stats.ac_pid) { + stats->ac_ppid = pid_stats.ac_ppid; + memcpy(stats->ac_comm, pid_stats.ac_comm, strlen(pid_stats.ac_comm) + 1); + } + + stats->virtmem += pid_stats.virtmem; + stats->coremem += pid_stats.coremem; + stats->read_bytes += pid_stats.read_bytes; + stats->write_bytes += pid_stats.write_bytes; + } + + closedir(task_dir); + + return 0; +} -- 2.7.4 From fe5e0dd127e30fe312166fa82adfe9111278fb99 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 31 Mar 2022 13:16:49 +0900 Subject: [PATCH 05/16] resource: process: Get initial stats of target process with taskstats Since open and read procfs task stat often cause performance degradation in the case that many process drivers are frequentyl set control. To reduce this overhead, now initial stats are retrieved by taskstats and 'pgid' which cannot be retrieved by taskstats is get lazily once at the first reading. Change-Id: I9bae9965a17192fbc0ab5789df45a782ab97ca9d Signed-off-by: Dongwoo Lee --- src/resource/resource-process.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/resource/resource-process.c b/src/resource/resource-process.c index 00fb14c..01ef3f9 100644 --- a/src/resource/resource-process.c +++ b/src/resource/resource-process.c @@ -199,6 +199,19 @@ static int process_get_context_data(const struct resource *res, strncpy((char *)data, ctx->comm, TS_COMM_LEN); break; case PROCESS_ATTR_PGID: + if (ctx->pgid < 0) { + char *stat_fields[PROCESS_STAT_FIELD_MAX]; + char buffer[BUFF_MAX]; + int ret; + + ret = kernel_get_process_stat_fields(ctx->tgid, buffer, + BUFF_MAX, stat_fields); + if (ret < 0) + break; + + ctx->pgid = atoi(stat_fields[PROCESS_STAT_FIELD_PGID]); + } + *((int *)data) = ctx->pgid; break; case PROCESS_ATTR_PPID: @@ -309,8 +322,6 @@ static int process_setup_tgid(const struct resource *res, const struct resource_control *ctrl, const void *data) { - char buf[BUFF_MAX]; - char *stat_fields[PROCESS_STAT_FIELD_MAX]; struct process_context *ctx; u_int64_t total_memory; int ret; @@ -328,20 +339,14 @@ static int process_setup_tgid(const struct resource *res, ctx->prev_total_time = get_total_cpu_time(); /* update initial status */ - ret = kernel_get_process_taskstats(&ctx->curr, ctx->tgid, false); - if (ret < 0) - return ret; - - ret = kernel_get_process_stat_fields(ctx->tgid, buf, BUFF_MAX, stat_fields); + ret = kernel_get_thread_group_taskstats(&ctx->curr, ctx->tgid, true); if (ret < 0) return ret; - /* save comm with removing parentheses */ - strncpy(ctx->comm, stat_fields[PROCESS_STAT_FIELD_COMM] + 1, - strlen(stat_fields[PROCESS_STAT_FIELD_COMM]) - 2 /* '(', ')' */); + memcpy(ctx->comm, ctx->curr.ac_comm, strlen(ctx->curr.ac_comm) + 1); - ctx->pgid = atoi(stat_fields[PROCESS_STAT_FIELD_PGID]); - ctx->ppid = atoi(stat_fields[PROCESS_STAT_FIELD_PPID]); + ctx->pgid = -1; + ctx->ppid = ctx->curr.ac_ppid; return 0; } -- 2.7.4 From ad5541e79c0d74a62e09f2ca5335f7b36c7cd25d Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 31 Mar 2022 13:32:25 +0900 Subject: [PATCH 06/16] resource: process-group: Use taskstats instead of reading procfs To lower the overhead of getting information about process, use taskstats instead of reading procfs while building group list. Moreover, two advantages can be gained as using taskstats directly: 1. Lower number of copy 2. Using taskstats accounting information without process driver Change-Id: I5242d25ab864b05674d9af01838d3401a356a1df Signed-off-by: Dongwoo Lee --- src/resource/resource-process-group.c | 152 ++++++++++++++++------------------ 1 file changed, 71 insertions(+), 81 deletions(-) diff --git a/src/resource/resource-process-group.c b/src/resource/resource-process-group.c index a56636d..31bb359 100644 --- a/src/resource/resource-process-group.c +++ b/src/resource/resource-process-group.c @@ -25,19 +25,13 @@ #define PROC_DIR_PATH "/proc/" -struct process_info { - pid_t pid; - pid_t ppid; - char comm[TS_COMM_LEN]; -}; - struct process_info_node { - struct process_info pi; + struct taskstats *stats; struct process_info_node *parent; }; struct process_group_context { - struct process_info root_pi; + struct taskstats root_stats; GPtrArray *pi_list; }; @@ -47,7 +41,7 @@ static int process_group_get_pid_list(const struct resource *res, { struct process_group_context *ctx; struct array_value *list = data; - struct process_info *pi; + struct process_info_node *node; int *data_array; int i; @@ -70,8 +64,8 @@ static int process_group_get_pid_list(const struct resource *res, list->length = ctx->pi_list->len; for (i = 0; i < list->length; i++) { - pi = g_ptr_array_index(ctx->pi_list, i); - data_array[i] = pi->pid; + node = g_ptr_array_index(ctx->pi_list, i); + data_array[i] = node->stats->ac_pid; } return 0; @@ -83,7 +77,7 @@ static int process_group_get_comm_list(const struct resource *res, { struct process_group_context *ctx; struct array_value *list = data; - struct process_info *pi; + struct process_info_node *node; char **data_array; int i; @@ -111,8 +105,8 @@ static int process_group_get_comm_list(const struct resource *res, list->length = ctx->pi_list->len; for (i = 0; i < list->length; i++) { - pi = g_ptr_array_index(ctx->pi_list, i); - data_array[i] = strdup(pi->comm); + node = g_ptr_array_index(ctx->pi_list, i); + data_array[i] = strdup(node->stats->ac_comm); if (!data_array[i]) { while (i > 0) free(data_array[--i]); @@ -151,9 +145,6 @@ static int process_group_setup_root_pid(const struct resource *res, const void *data) { struct process_group_context *ctx; - struct process_info *target; - char *statfields[PROCESS_STAT_FIELD_MAX]; - char buf[BUFF_MAX]; int target_pid; int ret; @@ -162,25 +153,20 @@ static int process_group_setup_root_pid(const struct resource *res, ctx = res->priv; - target = &ctx->root_pi; - target_pid = (int)(intptr_t)data; if (target_pid < 0) { - target->pid = target->ppid = -1; + ctx->root_stats.ac_pid = ctx->root_stats.ac_ppid = -1; return 0; } - ret = kernel_get_process_stat_fields(target_pid, buf, BUFF_MAX, statfields); + ret = kernel_get_process_taskstats(&ctx->root_stats, TASKSTATS_CMD_ATTR_PID, target_pid); if (ret < 0) { _E("target process pid is not valid"); - target->pid = target->ppid = -1; + ctx->root_stats.ac_pid = ctx->root_stats.ac_ppid = -1; return ret; } - target->pid = atoi(statfields[PROCESS_STAT_FIELD_PID]); - target->ppid = atoi(statfields[PROCESS_STAT_FIELD_PPID]); - return 0; } @@ -194,21 +180,29 @@ static const struct resource_control process_group_ctrls[] = { }, }; +static void free_node(void *_node) +{ + struct process_info_node *node = _node; + + if (node->stats) + free(node->stats); + + free(node); +} + static int process_group_prepare_update(struct resource *res) { struct process_group_context *ctx; struct process_info_node *pnode, *parent_pnode; - struct process_info *pi, *root_pi; struct dirent *task_entry; - char *statfields[PROCESS_STAT_FIELD_MAX]; - char buf[BUFF_MAX]; + struct taskstats *stats; GPtrArray *pi_list; GHashTableIter iter; gpointer key, value; GHashTable *process_hash; DIR *task_dir; - int len, ret = 0; - pid_t pid, ppid, pgrp; + int ret = 0; + pid_t pid; if (!res || !res->priv) return -EINVAL; @@ -219,7 +213,7 @@ static int process_group_prepare_update(struct resource *res) if (!task_dir) return -ESRCH; - process_hash = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free); + process_hash = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free_node); if (!process_hash) { ret = -ENOMEM; goto out_close; @@ -237,94 +231,79 @@ static int process_group_prepare_update(struct resource *res) pid = atoi(name); - ret = kernel_get_process_stat_fields(pid, buf, BUFF_MAX, statfields); - if (ret < 0) - continue; /* process might be terminated */ + if (pid == 2) + continue; + + stats = malloc(sizeof(struct taskstats)); + if (!stats) { + ret = -ENOMEM; + goto out_free_hash; + } - ppid = atoi(statfields[PROCESS_STAT_FIELD_PPID]); - pgrp = atoi(statfields[PROCESS_STAT_FIELD_PGID]); + ret = kernel_get_process_taskstats(stats, TASKSTATS_CMD_ATTR_PID, pid); + if (ret < 0) { + free(stats); + continue; /* process might be terminated */ + } /* except kthreads */ - if (pid == 2 || ppid == 2 || pgrp == 2) + if (stats->ac_ppid == 2 || strstr(stats->ac_comm, "irq/")) { + free(stats); continue; + } pnode = calloc(1, sizeof(struct process_info_node)); if (!pnode) { + free(stats); ret = -ENOMEM; goto out_free_hash; } - pnode->pi.pid = pid; - pnode->pi.ppid = ppid; + pnode->stats = stats; - len = strlen(statfields[PROCESS_STAT_FIELD_COMM]) - 2/* '(', ')' */; - len = (len < TS_COMM_LEN - 1) ? len : TS_COMM_LEN - 1; - strncpy(pnode->pi.comm, statfields[PROCESS_STAT_FIELD_COMM] + 1, len); - - if (g_hash_table_contains(process_hash, (gpointer)&pnode->pi.ppid)) { - parent_pnode = g_hash_table_lookup(process_hash, (gpointer)&pnode->pi.ppid); + if (g_hash_table_contains(process_hash, (gpointer)&pnode->stats->ac_ppid)) { + parent_pnode = g_hash_table_lookup(process_hash, + (gpointer)&pnode->stats->ac_ppid); pnode->parent = parent_pnode; } - g_hash_table_insert(process_hash, (gpointer)&pnode->pi.pid, (gpointer)pnode); + g_hash_table_insert(process_hash, (gpointer)&pnode->stats->ac_pid, (gpointer)pnode); } - pi_list = g_ptr_array_new_full(100, free); + pi_list = g_ptr_array_new_full(100, free_node); if (!pi_list) { ret = -ENOMEM; goto out_free_hash; } - root_pi = &ctx->root_pi; - - if (root_pi->pid < 0) { + if (ctx->root_stats.ac_pid < 0) { /* just add all processes into array if parent pid is negative */ g_hash_table_iter_init(&iter, process_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { pnode = (struct process_info_node *)value; - pi = malloc(sizeof(struct process_info)); - if (!pi) { - g_ptr_array_free(pi_list, true); - ctx->pi_list = NULL; - goto out_free_hash; - } - - memcpy(pi, &pnode->pi, sizeof(struct process_info)); - g_ptr_array_add(pi_list, pi); + g_ptr_array_add(pi_list, pnode); + g_hash_table_iter_steal(&iter); } } else { g_hash_table_iter_init(&iter, process_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { pnode = (struct process_info_node *)value; - if (root_pi->pid == pnode->pi.pid || root_pi->pid == pnode->pi.ppid) { + if (ctx->root_stats.ac_pid == pnode->stats->ac_pid + || ctx->root_stats.ac_pid == pnode->stats->ac_ppid) { - pi = malloc(sizeof(struct process_info)); - if (!pi) { - g_ptr_array_free(pi_list, true); - ctx->pi_list = NULL; - goto out_free_hash; - } - - memcpy(pi, &pnode->pi, sizeof(struct process_info)); - g_ptr_array_add(pi_list, pi); + g_ptr_array_add(pi_list, pnode); + g_hash_table_iter_steal(&iter); continue; } parent_pnode = pnode->parent; while (parent_pnode != NULL) { - if (parent_pnode->pi.ppid == root_pi->pid) { - pi = malloc(sizeof(struct process_info)); - if (!pi) { - g_ptr_array_free(pi_list, true); - ctx->pi_list = NULL; - goto out_free_hash; - } - - memcpy(pi, &pnode->pi, sizeof(struct process_info)); - g_ptr_array_add(pi_list, pi); + if (parent_pnode->stats->ac_ppid == ctx->root_stats.ac_pid) { + g_ptr_array_add(pi_list, pnode); + g_hash_table_iter_steal(&iter); break; } parent_pnode = parent_pnode->parent; @@ -357,7 +336,7 @@ static int process_group_init(struct resource *res) if (!ctx) return -ENOMEM; - ctx->root_pi.pid = ctx->root_pi.ppid = -1; + ctx->root_stats.ac_pid = ctx->root_stats.ac_ppid = -1; ctx->pi_list = NULL; res->priv = ctx; @@ -367,8 +346,19 @@ static int process_group_init(struct resource *res) static void process_group_exit(struct resource *res) { - if (res && res->priv) + struct process_group_context *ctx; + + if (res && res->priv) { + ctx = res->priv; + + if (ctx->pi_list) { + /* remove previous list */ + g_ptr_array_free(ctx->pi_list, true); + ctx->pi_list = NULL; + } + free(res->priv); + } } static const struct resource_driver process_group_driver = { -- 2.7.4 From e5b2952d3db58e339221f0e3161a2c1c34e45167 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Sun, 3 Apr 2022 23:14:22 +0900 Subject: [PATCH 07/16] resource: process-group: Add aggregated attributes for accounting stats To provide aggregated accounting information about the process group which includes target process and its child at a driver level, the structure managing the current process group is changed from list to hash, and it is preserved until root target is changed or a prcess in a group is terminated to maintain previous stats. Thus, the clients can retrieved aggregated accounting stats without create the individual process driver. Newly added attributes are as follows: - PROCESS_GROUP_ATTR_CPU_UTIL - PROCESS_GROUP_ATTR_DISK_READ_BPS - PROCESS_GROUP_ATTR_DISK_WRITE_BPS - PROCESS_GROUP_ATTR_MEM_VIRT - PROCESS_GROUP_ATTR_MEM_RSS Change-Id: I967da6110fb8568383c2ba096d599f51ce8e54e2 Signed-off-by: Dongwoo Lee --- lib/resource-monitor/resource-monitor.h | 5 + src/resource/resource-process-group.c | 381 ++++++++++++++++++++++++++------ 2 files changed, 322 insertions(+), 64 deletions(-) diff --git a/lib/resource-monitor/resource-monitor.h b/lib/resource-monitor/resource-monitor.h index 3b1b6cb..515ec10 100644 --- a/lib/resource-monitor/resource-monitor.h +++ b/lib/resource-monitor/resource-monitor.h @@ -127,6 +127,11 @@ extern "C" { /* Process List Resource */ #define PROCESS_GROUP_ATTR_PID_LIST BIT(0) /* DATA_TYPE_ARRAY(INT) */ #define PROCESS_GROUP_ATTR_COMM_LIST BIT(1) /* DATA_TYPE_ARRAY(STRING) */ +#define PROCESS_GROUP_ATTR_CPU_UTIL BIT(2) /* DATA_TYPE_DOUBLE */ +#define PROCESS_GROUP_ATTR_DISK_READ_BPS BIT(3) /* DATA_TYPE_UINT */ +#define PROCESS_GROUP_ATTR_DISK_WRITE_BPS BIT(4) /* DATA_TYPE_UINT */ +#define PROCESS_GROUP_ATTR_MEM_VIRT BIT(5) /* DATA_TYPE_UINT64 */ +#define PROCESS_GROUP_ATTR_MEM_RSS BIT(6) /* DATA_TYPE_UINT64 */ #define PROCESS_GROUP_CTRL_ROOT_PID BIT(0) diff --git a/src/resource/resource-process-group.c b/src/resource/resource-process-group.c index 31bb359..959ef43 100644 --- a/src/resource/resource-process-group.c +++ b/src/resource/resource-process-group.c @@ -26,15 +26,28 @@ #define PROC_DIR_PATH "/proc/" struct process_info_node { + pid_t tgid; + struct taskstats *prev; struct taskstats *stats; struct process_info_node *parent; }; struct process_group_context { - struct taskstats root_stats; - GPtrArray *pi_list; + pid_t pid; + GHashTable *pi_map; + struct { + double cpu_util; + u_int64_t mem_rss; + u_int64_t mem_virt; + u_int32_t disk_rbps; + u_int32_t disk_wbps; + } info; + u_int64_t prev_total_time; }; +static u_int64_t total_memory; +static long jiffy; + static int process_group_get_pid_list(const struct resource *res, const struct resource_attribute *attr, void *data) @@ -42,30 +55,32 @@ static int process_group_get_pid_list(const struct resource *res, struct process_group_context *ctx; struct array_value *list = data; struct process_info_node *node; + GHashTableIter iter; + gpointer key, value; int *data_array; - int i; + int i = 0; if (!res || !res->priv || !attr || !data) return -EINVAL; ctx = res->priv; - if (!ctx->pi_list) + if (!ctx->pi_map) return -EINVAL; if (list->data) free(list->data); - data_array = list->data = malloc(sizeof(int) * ctx->pi_list->len); + list->type = DATA_TYPE_INT; + list->length = g_hash_table_size(ctx->pi_map); + data_array = list->data = malloc(sizeof(int) * list->length); if (!data_array) return -ENOMEM; - list->type = DATA_TYPE_INT; - list->length = ctx->pi_list->len; - - for (i = 0; i < list->length; i++) { - node = g_ptr_array_index(ctx->pi_list, i); - data_array[i] = node->stats->ac_pid; + g_hash_table_iter_init(&iter, ctx->pi_map); + while (g_hash_table_iter_next(&iter, &key, &value)) { + node = (struct process_info_node *)value; + data_array[i++] = node->tgid; } return 0; @@ -78,15 +93,17 @@ static int process_group_get_comm_list(const struct resource *res, struct process_group_context *ctx; struct array_value *list = data; struct process_info_node *node; + GHashTableIter iter; + gpointer key, value; char **data_array; - int i; + int i = 0; if (!res || !res->priv || !attr || !data) return -EINVAL; ctx = res->priv; - if (!ctx->pi_list) + if (!ctx->pi_map) return -EINVAL; if (list->data) { @@ -96,16 +113,17 @@ static int process_group_get_comm_list(const struct resource *res, free(data_array); } + list->type = DATA_TYPE_STRING; + list->length = g_hash_table_size(ctx->pi_map); + /* last item will be null for boundary check */ - data_array = list->data = calloc(ctx->pi_list->len + 1, sizeof(char *)); + data_array = list->data = calloc(list->length + 1, sizeof(char *)); if (!data_array) return -ENOMEM; - list->type = DATA_TYPE_STRING; - list->length = ctx->pi_list->len; - - for (i = 0; i < list->length; i++) { - node = g_ptr_array_index(ctx->pi_list, i); + g_hash_table_iter_init(&iter, ctx->pi_map); + for (i = 0; g_hash_table_iter_next(&iter, &key, &value); i++) { + node = (struct process_info_node *)value; data_array[i] = strdup(node->stats->ac_comm); if (!data_array[i]) { while (i > 0) @@ -119,6 +137,87 @@ static int process_group_get_comm_list(const struct resource *res, return 0; } +static int process_group_get_cpu_util(const struct resource *res, + const struct resource_attribute *attr, + void *data) +{ + struct process_group_context *ctx; + double *util = (double *)data; + + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->pi_map || ctx->pid < 0) + return -EINVAL; + + *util = ctx->info.cpu_util; + + return 0; +} + +static int process_group_get_mem(const struct resource *res, + const struct resource_attribute *attr, + void *data) +{ + struct process_group_context *ctx; + u_int64_t *mem = (u_int64_t *)data; + + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->pi_map || ctx->pid < 0) + return -EINVAL; + + switch (attr->id) { + case PROCESS_GROUP_ATTR_MEM_RSS: + { + *mem = ctx->info.mem_rss; + break; + } + case PROCESS_GROUP_ATTR_MEM_VIRT: + { + *mem = ctx->info.mem_virt; + break; + } + default: + return -EINVAL; + } + + return 0; +} + +static int process_group_get_disk_bps(const struct resource *res, + const struct resource_attribute *attr, + void *data) +{ + struct process_group_context *ctx; + u_int32_t *bps = (u_int32_t *)data; + + if (!res || !res->priv || !attr || !data) + return -EINVAL; + + ctx = res->priv; + + if (!ctx->pi_map || ctx->pid < 0) + return -EINVAL; + + switch (attr->id) { + case PROCESS_GROUP_ATTR_DISK_READ_BPS: + *bps = ctx->info.disk_rbps; + break; + case PROCESS_GROUP_ATTR_DISK_WRITE_BPS: + *bps = ctx->info.disk_wbps; + break; + default: + return -EINVAL; + } + return 0; +} + static const struct resource_attribute process_group_attrs[] = { { .name = "PROCESS_GROUP_ATTR_PID_LIST", @@ -138,12 +237,54 @@ static const struct resource_attribute process_group_attrs[] = { .is_supported = resource_attr_supported_always, }, }, + { + .name = "PROCESS_GROUP_ATTR_CPU_UTIL", + .id = PROCESS_GROUP_ATTR_CPU_UTIL, + .type = DATA_TYPE_DOUBLE, + .ops = { + .get = process_group_get_cpu_util, + .is_supported = resource_attr_supported_always, + }, + }, { + .name = "PROCESS_GROUP_ATTR_DISK_READ_BPS", + .id = PROCESS_GROUP_ATTR_DISK_READ_BPS, + .type = DATA_TYPE_UINT, + .ops = { + .get = process_group_get_disk_bps, + .is_supported = resource_attr_supported_always, + }, + }, { + .name = "PROCESS_GROUP_ATTR_DISK_WRITE_BPS", + .id = PROCESS_GROUP_ATTR_DISK_WRITE_BPS, + .type = DATA_TYPE_UINT, + .ops = { + .get = process_group_get_disk_bps, + .is_supported = resource_attr_supported_always, + }, + }, { + .name = "PROCESS_GROUP_ATTR_MEM_VIRT", + .id = PROCESS_GROUP_ATTR_MEM_VIRT, + .type = DATA_TYPE_UINT64, + .ops = { + .get = process_group_get_mem, + .is_supported = resource_attr_supported_always, + }, + }, { + .name = "PROCESS_GROUP_ATTR_MEM_RSS", + .id = PROCESS_GROUP_ATTR_MEM_RSS, + .type = DATA_TYPE_UINT64, + .ops = { + .get = process_group_get_mem, + .is_supported = resource_attr_supported_always, + }, + }, }; static int process_group_setup_root_pid(const struct resource *res, const struct resource_control *ctrl, const void *data) { + struct taskstats stats; struct process_group_context *ctx; int target_pid; int ret; @@ -156,17 +297,19 @@ static int process_group_setup_root_pid(const struct resource *res, target_pid = (int)(intptr_t)data; if (target_pid < 0) { - ctx->root_stats.ac_pid = ctx->root_stats.ac_ppid = -1; + ctx->pid = -1; return 0; } - ret = kernel_get_process_taskstats(&ctx->root_stats, TASKSTATS_CMD_ATTR_PID, target_pid); + ret = kernel_get_process_taskstats(&stats, TASKSTATS_CMD_ATTR_PID, target_pid); if (ret < 0) { _E("target process pid is not valid"); - ctx->root_stats.ac_pid = ctx->root_stats.ac_ppid = -1; + ctx->pid = -1; return ret; } + ctx->pid = stats.ac_pid; + return 0; } @@ -180,29 +323,119 @@ static const struct resource_control process_group_ctrls[] = { }, }; +#define saturatingSub(a, b) (a > b ? a - b : 0) + static void free_node(void *_node) { struct process_info_node *node = _node; + if (node->prev) + free(node->prev); if (node->stats) free(node->stats); - free(node); } +static u_int64_t get_total_cpu_time(void) +{ + struct cpu_stat cpu_stat; + u_int64_t total_time; + int ret; + + ret = kernel_get_total_cpu_stat(&cpu_stat); + if (ret < 0) { + _E("failed to get cpu stat"); + return 0; + }; + + total_time = cpu_stat.user + cpu_stat.system + cpu_stat.nice + cpu_stat.idle; + total_time += cpu_stat.wait + cpu_stat.hard_irq + cpu_stat.soft_irq; + + return total_time; +} + +static int update_aggr_taskstats(struct process_group_context *ctx) +{ + struct process_info_node *node; + struct taskstats *prev, *curr; + u_int64_t total_time; + int online, nproc; + double cpu_period; + GHashTableIter iter; + gpointer key, value; + pid_t pid; + int ret; + + memset(&ctx->info, 0, sizeof(ctx->info)); + + nproc = g_hash_table_size(ctx->pi_map); + online = kernel_get_online_cpu_num(); + total_time = get_total_cpu_time(); + + cpu_period = (double)saturatingSub(total_time, ctx->prev_total_time) / online; + + ctx->prev_total_time = total_time; + + g_hash_table_iter_init(&iter, ctx->pi_map); + while (g_hash_table_iter_next(&iter, &key, &value)) { + node = (struct process_info_node *)value; + + pid = node->tgid; + prev = node->prev; + + curr = calloc(1, sizeof(struct taskstats)); + if (!curr) + return -ENOMEM; + + ret = kernel_get_thread_group_taskstats(curr, pid, true); + if (ret < 0) { + free(curr); + g_hash_table_iter_remove(&iter); + continue; + } + + if (!prev) { + node->stats = node->prev = curr; + continue; + } + + if (cpu_period >= 1E-6) { + double util; + + util = (double)(curr->ac_utime + curr->ac_stime); + util -= (double)(prev->ac_utime + prev->ac_stime); + util *= (jiffy / (cpu_period * 10000.0)); + util = min(util, 100.0); + + ctx->info.cpu_util += (util / nproc); + } + + ctx->info.mem_virt += (curr->virtmem * 1024 * 1024) / curr->ac_stime; + ctx->info.mem_rss += (curr->coremem * 1024 * 1024) / curr->ac_stime; + ctx->info.disk_rbps += ((curr->read_bytes - prev->read_bytes) * 1000000) + / (curr->ac_etime - prev->ac_etime); + ctx->info.disk_wbps += ((curr->write_bytes - prev->write_bytes) * 1000000) + / (curr->ac_etime - prev->ac_etime); + free(prev); + node->prev = curr; + node->stats = curr; + } + + return 0; +} + static int process_group_prepare_update(struct resource *res) { struct process_group_context *ctx; struct process_info_node *pnode, *parent_pnode; struct dirent *task_entry; struct taskstats *stats; - GPtrArray *pi_list; GHashTableIter iter; gpointer key, value; GHashTable *process_hash; DIR *task_dir; int ret = 0; - pid_t pid; + pid_t tgid; if (!res || !res->priv) return -EINVAL; @@ -229,9 +462,9 @@ static int process_group_prepare_update(struct resource *res) if (name[0] < '0' || name[0] > '9') continue; - pid = atoi(name); + tgid = atoi(name); - if (pid == 2) + if (tgid == 2) continue; stats = malloc(sizeof(struct taskstats)); @@ -240,7 +473,7 @@ static int process_group_prepare_update(struct resource *res) goto out_free_hash; } - ret = kernel_get_process_taskstats(stats, TASKSTATS_CMD_ATTR_PID, pid); + ret = kernel_get_process_taskstats(stats, TASKSTATS_CMD_ATTR_PID, tgid); if (ret < 0) { free(stats); continue; /* process might be terminated */ @@ -260,6 +493,7 @@ static int process_group_prepare_update(struct resource *res) } pnode->stats = stats; + pnode->tgid = tgid; if (g_hash_table_contains(process_hash, (gpointer)&pnode->stats->ac_ppid)) { parent_pnode = g_hash_table_lookup(process_hash, @@ -268,57 +502,62 @@ static int process_group_prepare_update(struct resource *res) pnode->parent = parent_pnode; } - g_hash_table_insert(process_hash, (gpointer)&pnode->stats->ac_pid, (gpointer)pnode); + g_hash_table_insert(process_hash, (gpointer)&pnode->tgid, (gpointer)pnode); } - pi_list = g_ptr_array_new_full(100, free_node); - if (!pi_list) { - ret = -ENOMEM; - goto out_free_hash; + g_hash_table_iter_init(&iter, ctx->pi_map); + while (g_hash_table_iter_next(&iter, &key, &value)) { + pnode = (struct process_info_node *)value; + if (!g_hash_table_contains(process_hash, key)) { + pnode = (struct process_info_node *)value; + + g_hash_table_iter_remove(&iter); + } } - if (ctx->root_stats.ac_pid < 0) { + if (ctx->pid < 0) { /* just add all processes into array if parent pid is negative */ g_hash_table_iter_init(&iter, process_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { - pnode = (struct process_info_node *)value; + if (!g_hash_table_contains(ctx->pi_map, key)) { + pnode = (struct process_info_node *)value; - g_ptr_array_add(pi_list, pnode); - g_hash_table_iter_steal(&iter); + g_hash_table_insert(ctx->pi_map, key, pnode); + g_hash_table_iter_steal(&iter); + } } } else { g_hash_table_iter_init(&iter, process_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { pnode = (struct process_info_node *)value; - if (ctx->root_stats.ac_pid == pnode->stats->ac_pid - || ctx->root_stats.ac_pid == pnode->stats->ac_ppid) { - - g_ptr_array_add(pi_list, pnode); - g_hash_table_iter_steal(&iter); - continue; - } - - parent_pnode = pnode->parent; - while (parent_pnode != NULL) { - if (parent_pnode->stats->ac_ppid == ctx->root_stats.ac_pid) { - g_ptr_array_add(pi_list, pnode); + if (!g_hash_table_contains(ctx->pi_map, key)) { + if (ctx->pid == pnode->stats->ac_pid + || ctx->pid == pnode->stats->ac_ppid) { + g_hash_table_insert(ctx->pi_map, key, pnode); g_hash_table_iter_steal(&iter); - break; + continue; + } + + parent_pnode = pnode->parent; + while (parent_pnode != NULL) { + if (parent_pnode->stats->ac_ppid == ctx->pid) { + g_hash_table_insert(ctx->pi_map, key, pnode); + g_hash_table_iter_steal(&iter); + break; + } + parent_pnode = parent_pnode->parent; } - parent_pnode = parent_pnode->parent; } } - } - if (ctx->pi_list) { - /* remove previous list */ - g_ptr_array_free(ctx->pi_list, true); - ctx->pi_list = NULL; + ret = update_aggr_taskstats(ctx); + if (ret < 0) { + ret = -EINVAL; + goto out_free_hash; + } } - ctx->pi_list = pi_list; - ret = 0; out_free_hash: g_hash_table_destroy(process_hash); @@ -331,13 +570,28 @@ out_close: static int process_group_init(struct resource *res) { struct process_group_context *ctx; + int ret; + + if (jiffy == 0) { + /* get system USER_HZ at once */ + jiffy = sysconf(_SC_CLK_TCK); + if (jiffy < 0) + return -EINVAL; + } + + if (total_memory == 0) { + /* get system total memory once at init*/ + ret = kernel_get_memory_total(&total_memory); + if (ret < 0) + return -EINVAL; + } ctx = malloc(sizeof(struct process_group_context)); if (!ctx) return -ENOMEM; - ctx->root_stats.ac_pid = ctx->root_stats.ac_ppid = -1; - ctx->pi_list = NULL; + ctx->pid = -1; + ctx->pi_map = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free_node); res->priv = ctx; @@ -351,10 +605,9 @@ static void process_group_exit(struct resource *res) if (res && res->priv) { ctx = res->priv; - if (ctx->pi_list) { - /* remove previous list */ - g_ptr_array_free(ctx->pi_list, true); - ctx->pi_list = NULL; + if (ctx->pi_map) { + g_hash_table_destroy(ctx->pi_map); + ctx->pi_map = NULL; } free(res->priv); -- 2.7.4 From 71da9223e76231608dc614f0a46eeb56d0d7ef3d Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 11 Apr 2022 20:28:37 +0900 Subject: [PATCH 08/16] resource: process-group: Fix unnecessary assignment and meaningless code Change-Id: I600fc27afa7ecb95853bc492bd997ee8d99d1e9a Signed-off-by: Dongwoo Lee --- src/resource/resource-process-group.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/resource/resource-process-group.c b/src/resource/resource-process-group.c index 959ef43..caab3a0 100644 --- a/src/resource/resource-process-group.c +++ b/src/resource/resource-process-group.c @@ -387,7 +387,7 @@ static int update_aggr_taskstats(struct process_group_context *ctx) if (!curr) return -ENOMEM; - ret = kernel_get_thread_group_taskstats(curr, pid, true); + ret = kernel_get_thread_group_taskstats(curr, pid, false); if (ret < 0) { free(curr); g_hash_table_iter_remove(&iter); @@ -395,7 +395,7 @@ static int update_aggr_taskstats(struct process_group_context *ctx) } if (!prev) { - node->stats = node->prev = curr; + node->prev = curr; continue; } @@ -418,7 +418,6 @@ static int update_aggr_taskstats(struct process_group_context *ctx) / (curr->ac_etime - prev->ac_etime); free(prev); node->prev = curr; - node->stats = curr; } return 0; @@ -506,14 +505,9 @@ static int process_group_prepare_update(struct resource *res) } g_hash_table_iter_init(&iter, ctx->pi_map); - while (g_hash_table_iter_next(&iter, &key, &value)) { - pnode = (struct process_info_node *)value; - if (!g_hash_table_contains(process_hash, key)) { - pnode = (struct process_info_node *)value; - + while (g_hash_table_iter_next(&iter, &key, &value)) + if (!g_hash_table_contains(process_hash, key)) g_hash_table_iter_remove(&iter); - } - } if (ctx->pid < 0) { /* just add all processes into array if parent pid is negative */ -- 2.7.4 From a193fd0fb47a37e666c38f8eec46ebad594f5143 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Fri, 8 Apr 2022 12:04:08 +0900 Subject: [PATCH 09/16] monitor: resource: Add timestamp support To provide timeline information of resource update, now provides timestamp as start and end time of update. It is included in resource json as "res_ts" with "start" and "end" object, and it also can be retrieved with following new libpass function: - pass_resource_monitor_get_resource_timestamp() Change-Id: Iad2cf8bb1d1100f4ded44ce5e19aeb119c65575e Signed-off-by: Dongwoo Lee --- include/util/request.h | 1 + include/util/resource.h | 15 ++++++++++++- lib/resource-monitor/resource-monitor.c | 32 ++++++++++++++++++++++++++++ lib/resource-monitor/resource-monitor.h | 11 ++++++++++ src/monitor/request-handler.c | 37 +++++++++++++++++++++++++++++++++ src/util/resource.c | 17 +++++++++++++++ 6 files changed, 112 insertions(+), 1 deletion(-) diff --git a/include/util/request.h b/include/util/request.h index fcee614..44d2047 100644 --- a/include/util/request.h +++ b/include/util/request.h @@ -44,6 +44,7 @@ enum { REQUEST_GET_VALUE_DOUBLE, REQUEST_GET_VALUE_STRING, REQUEST_GET_VALUE_ARRAY, + REQUEST_GET_RESOURCE_TS, REQUEST_MAX, }; diff --git a/include/util/resource.h b/include/util/resource.h index 71d756f..97a1b93 100644 --- a/include/util/resource.h +++ b/include/util/resource.h @@ -20,6 +20,7 @@ #ifndef __RESOURCE_H__ #define __RESOURCE_H__ +#include #include #include #include "common.h" @@ -136,6 +137,9 @@ struct resource { const struct resource_control *ctrls; u_int64_t attr_interest; u_int64_t attr_supported; + + int64_t ts_start; + int64_t ts_end; }; #define RESOURCE_DRIVER_REGISTER(resource_driver) \ @@ -180,8 +184,9 @@ resource_attr_supported_always(const struct resource *resource, } int get_resource_attrs_json(struct resource *resource, char **json_string); - int get_resource_attr_json(struct resource *resource, u_int64_t attr_id, char **json_string); +int get_resource_list_json(char **json_string); + 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); @@ -194,4 +199,12 @@ int get_resource_attr_ptr(struct resource *resource, u_int64_t attr_id, void **d int set_resource_attr_interest(struct resource *resource, u_int64_t interest_mask); int unset_resource_attr_interest(struct resource *resource, u_int64_t interest_mask); + +inline __attribute__((always_inline)) int64_t get_time_now(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return (int64_t)tv.tv_sec * 1000000 + (int64_t)tv.tv_usec; +} #endif diff --git a/lib/resource-monitor/resource-monitor.c b/lib/resource-monitor/resource-monitor.c index af25357..02361f9 100644 --- a/lib/resource-monitor/resource-monitor.c +++ b/lib/resource-monitor/resource-monitor.c @@ -924,3 +924,35 @@ int pass_resource_monitor_get_array_string(int id, int res_id, u_int64_t attr_id { return pass_resource_monitor_get_array(id, res_id, attr_id, DATA_TYPE_STRING, (void **)array, length); } + +int pass_resource_monitor_get_resource_timestamp(int id, int res_id, int64_t *start, int64_t *end) +{ + char buffer[GENERIC_BUFF_MAX + 1]; + int buffer_len; + int response_req; + int ret; + + buffer_len = sprintf(buffer, "%d$%d", REQUEST_GET_RESOURCE_TS, res_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, GENERIC_BUFF_MAX, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + return -EIO; + } + buffer[buffer_len] = '\0'; + + if (sscanf(buffer, "%d$%"PRId64"$%"PRId64"$%d", &response_req, start, end, &ret) < 3) + return -EINVAL; + + if (response_req != REQUEST_GET_VALUE_INT64) { + _E("[libpass] wrong response"); + return -EINVAL; + } + + return ret; +} diff --git a/lib/resource-monitor/resource-monitor.h b/lib/resource-monitor/resource-monitor.h index 515ec10..c943dc4 100644 --- a/lib/resource-monitor/resource-monitor.h +++ b/lib/resource-monitor/resource-monitor.h @@ -266,6 +266,17 @@ int pass_resource_monitor_get_array_uint64(int id, int res_id, u_int64_t attr, u int pass_resource_monitor_get_array_double(int id, int res_id, u_int64_t attr, double **array, int *length); int pass_resource_monitor_get_array_string(int id, int res_id, u_int64_t attr, char ***array, int *length); +/** + * @brief Get timestamp of the latest resource update + * @param[in] Resource monitor id + * @param[in] Resource id + * @param[out] start time of update + * @param[out] end time of update + * @return @ 0 on success, otherwise a negative error value + */ + +int pass_resource_monitor_get_resource_timestamp(int id, int res_id, int64_t *start, int64_t *end); + #ifdef __cplusplus } #endif diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 3bbea40..2bad112 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -454,6 +454,32 @@ handle_request_get_value_array(struct request_client *client, char *args, struct return get_resource_attr_array(res, attr_id, arr); } +static int +handle_request_get_resource_ts(struct request_client *client, char *args, + int64_t *start, int64_t *end) +{ + struct resource *res; + int resource_id; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_GET_RESOURCE_TS args: + * - + */ + resource_id = atoi(args); + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + *start = res->ts_start; + *end = res->ts_end; + + return 0; +} + static int split_request_type_and_args(char *buffer, char **args) { char *request_type_str; @@ -690,6 +716,17 @@ static int handle_request(struct request_client *client, char *request) } } break; + case REQUEST_GET_RESOURCE_TS: + { + int64_t start, end; + + ret = handle_request_get_resource_ts(client, args, &start, &end); + if (ret < 0) + _D("failed to get value"); + + ADD_RESPONSE(response, buffer_len, "%"PRId64"$%"PRId64"$", start, end); + } + break; default: _E("Invliad request type: %d", request_type); ret = -EINVAL; diff --git a/src/util/resource.c b/src/util/resource.c index aefe3cc..abe7b49 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -254,6 +254,8 @@ int update_resource_attrs(struct resource *resource) if (!resource || !resource->type) return -EINVAL; + resource->ts_start = get_time_now(); + if (resource->driver && resource->driver->ops.prepare_update) { ret = resource->driver->ops.prepare_update(resource); if (ret < 0) @@ -270,6 +272,8 @@ int update_resource_attrs(struct resource *resource) } } + resource->ts_end = get_time_now(); + return 0; } @@ -468,6 +472,7 @@ static void _put_resource_attr_json(json_object *jobj_attr) int get_resource_attrs_json(struct resource *resource, char **json_string) { json_object *jobj_root, *jobj_res_name, *jobj_res_type, *jobj_res_attrs, *jobj_attr; + json_object *jobj_res_ts, *jobj_ts_start, *jobj_ts_end; const struct resource_attribute *attr; const struct resource_attribute_value *attr_value; int i; @@ -493,18 +498,30 @@ int get_resource_attrs_json(struct resource *resource, char **json_string) json_object_array_add(jobj_res_attrs, jobj_attr); } + jobj_res_ts = json_object_new_object(); + jobj_ts_start = json_object_new_int64(resource->ts_start); + jobj_ts_end = json_object_new_int64(resource->ts_end); + + json_object_object_add(jobj_res_ts, "start", jobj_ts_start); + json_object_object_add(jobj_res_ts, "end", jobj_ts_end); + json_object_object_add(jobj_root, "res_name", jobj_res_name); json_object_object_add(jobj_root, "res_type", jobj_res_type); json_object_object_add(jobj_root, "res_attrs", jobj_res_attrs); + json_object_object_add(jobj_root, "res_ts", jobj_res_ts); *json_string = strdup(json_object_to_json_string(jobj_root)); + json_object_object_del(jobj_res_ts, "end"); + json_object_object_del(jobj_res_ts, "start"); + for (i = 0; i < json_object_array_length(jobj_res_attrs); i++) { jobj_attr = json_object_array_get_idx(jobj_res_attrs, i); _put_resource_attr_json(jobj_attr); } json_object_array_del_idx(jobj_res_attrs, 0, json_object_array_length(jobj_res_attrs)); + json_object_object_del(jobj_root, "res_ts"); json_object_object_del(jobj_root, "res_attrs"); json_object_object_del(jobj_root, "res_type"); json_object_object_del(jobj_root, "res_name"); -- 2.7.4 From bb23b347050aa995adaffb8831ffbc9eea0955a1 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Fri, 8 Apr 2022 16:59:30 +0900 Subject: [PATCH 10/16] monitor: resource: Add function for getting resource and its attributes list To provide way to manage monitoring module without static list, now json type information for resource and its attributes list can be retrieved with following function: - pass_resource_monitor_get_resource_list_json() Change-Id: Ib9c8787a081f674fc1d6bdf12d9d027cca4b0352 Signed-off-by: Dongwoo Lee --- include/util/request.h | 1 + lib/resource-monitor/resource-monitor.c | 9 +++ lib/resource-monitor/resource-monitor.h | 8 +++ src/monitor/request-handler.c | 11 ++- src/util/resource.c | 122 ++++++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 1 deletion(-) diff --git a/include/util/request.h b/include/util/request.h index 44d2047..c640830 100644 --- a/include/util/request.h +++ b/include/util/request.h @@ -45,6 +45,7 @@ enum { REQUEST_GET_VALUE_STRING, REQUEST_GET_VALUE_ARRAY, REQUEST_GET_RESOURCE_TS, + REQUEST_GET_RESOURCE_LIST_JSON, REQUEST_MAX, }; diff --git a/lib/resource-monitor/resource-monitor.c b/lib/resource-monitor/resource-monitor.c index 02361f9..fc70700 100644 --- a/lib/resource-monitor/resource-monitor.c +++ b/lib/resource-monitor/resource-monitor.c @@ -461,6 +461,9 @@ static int pass_resource_monitor_get_json(int id, char *json_string, int request buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d$%d$%"PRIu64, request_type, resource_id, attr_id); break; + case REQUEST_GET_RESOURCE_LIST_JSON: + buffer_len = snprintf(buffer, HUGE_BUFF_MAX, "%d", request_type); + break; default: va_end(args); free(buffer); @@ -512,6 +515,12 @@ int pass_resource_monitor_get_value_json(int id, int resource_id, u_int64_t attr } EXPORT +int pass_resource_monitor_get_resource_list_json(int id, char *json_string) +{ + return pass_resource_monitor_get_json(id, json_string, REQUEST_GET_RESOURCE_LIST_JSON); +} + +EXPORT int pass_resource_monitor_get_value_int(int id, int resource_id, u_int64_t attr_id, int32_t *value) { char buffer[GENERIC_BUFF_MAX + 1]; diff --git a/lib/resource-monitor/resource-monitor.h b/lib/resource-monitor/resource-monitor.h index c943dc4..4644d96 100644 --- a/lib/resource-monitor/resource-monitor.h +++ b/lib/resource-monitor/resource-monitor.h @@ -277,6 +277,14 @@ int pass_resource_monitor_get_array_string(int id, int res_id, u_int64_t attr, c int pass_resource_monitor_get_resource_timestamp(int id, int res_id, int64_t *start, int64_t *end); +/** + * @brief Get all available resource list which monitoring module supported + * @param[in] Resource monitor id + * @param[out] JSON type string for resource + * @return @c positive integer as resource count on success, otherwise a negative error value + */ +int pass_resource_monitor_get_resource_list_json(int id, char *json_string); + #ifdef __cplusplus } #endif diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 2bad112..184631d 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -255,7 +255,7 @@ handle_request_get_json(struct request_client *client, char *args, u_int64_t attr_id; int resource_id; - if (!client || !args) + if (!client) return -ENOENT; /** @@ -263,6 +263,8 @@ handle_request_get_json(struct request_client *client, char *args, * - * Format of REQUEST_GET_VALUE_JSON args: * - : + * Format of REQUEST_GET_RESOURCE_LIST_JSON args: + * - NO ARGUMENTS */ switch (request_type) { case REQUEST_GET_RESOURCE_JSON: @@ -272,6 +274,8 @@ handle_request_get_json(struct request_client *client, char *args, if (sscanf(args, "%d$%"PRIu64, &resource_id, &attr_id) < 2) return -EINVAL; break; + case REQUEST_GET_RESOURCE_LIST_JSON: + goto skip_res; default: return -EINVAL; } @@ -280,11 +284,14 @@ handle_request_get_json(struct request_client *client, char *args, if (!res) return -EINVAL; +skip_res: switch (request_type) { case REQUEST_GET_RESOURCE_JSON: return get_resource_attrs_json(res, json_string); case REQUEST_GET_VALUE_JSON: return get_resource_attr_json(res, attr_id, json_string); + case REQUEST_GET_RESOURCE_LIST_JSON: + return get_resource_list_json(json_string); default: return -EINVAL; } @@ -511,6 +518,7 @@ static int handle_request(struct request_client *client, char *request) case REQUEST_GET_RESOURCE_JSON: case REQUEST_GET_VALUE_JSON: case REQUEST_GET_VALUE_ARRAY: + case REQUEST_GET_RESOURCE_LIST_JSON: buffer_len = HUGE_BUFF_MAX + 1; break; default: @@ -573,6 +581,7 @@ static int handle_request(struct request_client *client, char *request) break; case REQUEST_GET_RESOURCE_JSON: case REQUEST_GET_VALUE_JSON: + case REQUEST_GET_RESOURCE_LIST_JSON: { char *json_string; diff --git a/src/util/resource.c b/src/util/resource.c index abe7b49..9c2233d 100644 --- a/src/util/resource.c +++ b/src/util/resource.c @@ -551,6 +551,128 @@ int get_resource_attr_json(struct resource *resource, u_int64_t attr_id, char ** return 0; } +static json_object *get_resource_driver_json(const struct resource_driver *driver) +{ + json_object *jobj_drv, *jobj_drv_name, *jobj_drv_type; + json_object *jobj_drv_attrs_array, *jobj_drv_attr, *jobj_drv_ctrls_array, *jobj_drv_ctrl; + json_object *jobj_drv_attr_name, *jobj_drv_attr_type, *jobj_drv_attr_id; + json_object *jobj_drv_ctrl_name, *jobj_drv_ctrl_id; + const struct resource_attribute *attr; + const struct resource_control *ctrl; + int i; + + jobj_drv = json_object_new_object(); + + jobj_drv_name = json_object_new_string(driver->name); + jobj_drv_type = json_object_new_int(driver->type); + + jobj_drv_attrs_array = json_object_new_array(); + + for (i = 0; i < driver->num_attrs; i++) { + attr = &driver->attrs[i]; + + jobj_drv_attr = json_object_new_object(); + + jobj_drv_attr_name = json_object_new_string(attr->name); + jobj_drv_attr_type = json_object_new_int(attr->type); + jobj_drv_attr_id = json_object_new_uint64(attr->id); + + json_object_object_add(jobj_drv_attr, "name", jobj_drv_attr_name); + json_object_object_add(jobj_drv_attr, "type", jobj_drv_attr_type); + json_object_object_add(jobj_drv_attr, "id", jobj_drv_attr_id); + + json_object_array_add(jobj_drv_attrs_array, jobj_drv_attr); + } + + jobj_drv_ctrls_array = json_object_new_array(); + + for (i = 0; i < driver->num_ctrls; i++) { + ctrl = &driver->ctrls[i]; + + jobj_drv_ctrl = json_object_new_object(); + + jobj_drv_ctrl_name = json_object_new_string(ctrl->name); + jobj_drv_ctrl_id = json_object_new_uint64(ctrl->id); + + json_object_object_add(jobj_drv_ctrl, "name", jobj_drv_ctrl_name); + json_object_object_add(jobj_drv_ctrl, "id", jobj_drv_ctrl_id); + + json_object_array_add(jobj_drv_ctrls_array, jobj_drv_ctrl); + } + + json_object_object_add(jobj_drv, "name", jobj_drv_name); + json_object_object_add(jobj_drv, "type", jobj_drv_type); + json_object_object_add(jobj_drv, "attrs", jobj_drv_attrs_array); + json_object_object_add(jobj_drv, "ctrls", jobj_drv_ctrls_array); + + return jobj_drv; +} + +void put_resource_driver_json(json_object *jobj_drv) +{ + json_object *jobj_array, *jobj_obj; + int i; + + if (json_object_object_get_ex(jobj_drv, "ctrls", &jobj_array)) { + for (i = 0; i < json_object_array_length(jobj_array); i++) { + jobj_obj = json_object_array_get_idx(jobj_array, i); + + json_object_object_del(jobj_obj, "id"); + json_object_object_del(jobj_obj, "name"); + } + json_object_array_del_idx(jobj_array, 0, json_object_array_length(jobj_array)); + } + + if (json_object_object_get_ex(jobj_drv, "attrs", &jobj_array)) { + for (i = 0; i < json_object_array_length(jobj_array); i++) { + jobj_obj = json_object_array_get_idx(jobj_array, i); + + json_object_object_del(jobj_obj, "id"); + json_object_object_del(jobj_obj, "type"); + json_object_object_del(jobj_obj, "name"); + } + json_object_array_del_idx(jobj_array, 0, json_object_array_length(jobj_array)); + } + + json_object_object_del(jobj_drv, "ctrls"); + json_object_object_del(jobj_drv, "attrs"); + json_object_object_del(jobj_drv, "type"); + json_object_object_del(jobj_drv, "name"); +} + +int get_resource_list_json(char **json_string) +{ + const struct resource_driver *driver; + json_object *jobj_root, *jobj_drvs_array, *jobj_drv; + int i; + + jobj_root = json_object_new_object(); + jobj_drvs_array = json_object_new_array(); + + for (i = 0; i < g_list_length(g_resource_driver_head); i++) { + driver = g_list_nth(g_list_first(g_resource_driver_head), i)->data; + + jobj_drv = get_resource_driver_json(driver); + json_object_array_add(jobj_drvs_array, jobj_drv); + } + + json_object_object_add(jobj_root, "resources", jobj_drvs_array); + + *json_string = strdup(json_object_to_json_string(jobj_root)); + + for (i = 0; i < json_object_array_length(jobj_drvs_array); i++) { + jobj_drv = json_object_array_get_idx(jobj_drvs_array, i); + + put_resource_driver_json(jobj_drv); + } + json_object_array_del_idx(jobj_drvs_array, 0, json_object_array_length(jobj_drvs_array)); + + json_object_object_del(jobj_root, "resources"); + json_object_put(jobj_root); + + return 0; +} + int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data) { struct resource_attribute_value *attr_value = NULL; -- 2.7.4 From b858204d0487a359df0e1843bb3eb42c1d9b3c02 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 12 May 2022 16:09:32 +0900 Subject: [PATCH 11/16] util: timer: Fix possible dangling pointer and memory leak Change-Id: I466617b365e91108c0ed3cdf1d95c8a237feaad8 Signed-off-by: Dongwoo Lee --- src/util/timer.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/util/timer.c b/src/util/timer.c index 849baef..26aad82 100644 --- a/src/util/timer.c +++ b/src/util/timer.c @@ -38,19 +38,11 @@ struct uevent_data { int fd; }; -static gint __compare_timer_id(gconstpointer data, gconstpointer input) -{ - guint id= *(guint *)data; - guint input_id = *(guint *)input; - - return (id == input_id) ? 0 : -1; -} - static bool find_timer(int id) { GList *node; - node = g_list_find_custom(g_timer_list, &id, __compare_timer_id); + node = g_list_find(g_timer_list, GINT_TO_POINTER(id)); if (!node) return false; @@ -89,8 +81,7 @@ int add_timer_handler(unsigned int interval, if (!timer_id) return -EPERM; - g_timer_list = g_list_append(g_timer_list, - (gpointer)&timer_id); + g_timer_list = g_list_append(g_timer_list, GINT_TO_POINTER(timer_id)); return timer_id; } @@ -101,8 +92,7 @@ void delete_timer_handler(int timer_id) return; g_source_remove(timer_id); - g_timer_list = g_list_remove(g_timer_list, - (gpointer)&timer_id); + g_timer_list = g_list_remove(g_timer_list, GINT_TO_POINTER(timer_id)); } struct udev_monitor *add_uevent_handler( @@ -215,6 +205,7 @@ void delete_uevent_handler(struct udev_monitor *udev_monitor) g_source_remove(uevent_data->fd); uevent_data->fd = -1; + free(uevent_data); } void init_timer(void) @@ -235,7 +226,7 @@ void exit_timer(void) */ g_list_free(g_timer_list); - g_list_free(g_uevent_list); + g_list_free_full(g_uevent_list, free); g_timer_list = NULL; g_uevent_list = NULL; -- 2.7.4 From bd3d91617c9448074267869d6ec6f21df2ba2d1f Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Mon, 30 May 2022 15:59:21 +0900 Subject: [PATCH 12/16] resource: memory: Add MEMORY_ATTR_SWAP_TOTAL and MEMORY_ATTR_SWAP_FREE attributes Change-Id: I8f6e3ff274c429fe2e5d2f9378ea4e8ae18dccaf Signed-off-by: Sung-hun Kim --- lib/resource-monitor/resource-monitor.h | 2 ++ src/resource/resource-memory.c | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lib/resource-monitor/resource-monitor.h b/lib/resource-monitor/resource-monitor.h index 4644d96..5bfbb3f 100644 --- a/lib/resource-monitor/resource-monitor.h +++ b/lib/resource-monitor/resource-monitor.h @@ -86,6 +86,8 @@ extern "C" { #define MEMORY_ATTR_CACHED BIT(4) /* DATA_TYPE_UINT64 */ #define MEMORY_ATTR_CMA_TOTAL BIT(5) /* DATA_TYPE_UINT64 */ #define MEMORY_ATTR_CMA_FREE BIT(6) /* DATA_TYPE_UINT64 */ +#define MEMORY_ATTR_SWAP_TOTAL BIT(7) /* DATA_TYPE_UINT64 */ +#define MEMORY_ATTR_SWAP_FREE BIT(8) /* DATA_TYPE_UINT64 */ /* Battery Resource */ #define BATTERY_ATTR_CAPACITY BIT(0) /* DATA_TYPE_INT */ diff --git a/src/resource/resource-memory.c b/src/resource/resource-memory.c index f0b8782..48c627d 100644 --- a/src/resource/resource-memory.c +++ b/src/resource/resource-memory.c @@ -38,6 +38,7 @@ #define PROC_MEM_INFO_BUFFER "Buffers" #define PROC_MEM_INFO_CACHED "Cached" #define PROC_MEM_INFO_CMA_FREE "CmaFree" +#define PROC_MEM_INFO_SWAP_FREE "SwapFree" static int memory_get_cma_total(u_int64_t *val) { @@ -57,6 +58,24 @@ static int memory_get_cma_total(u_int64_t *val) return 0; } +static int memory_get_swap_total(u_int64_t *val) +{ + static u_int64_t swap_total = 0; + int ret; + + if (!swap_total) { + ret = kernel_get_memory_info("SwapTotal", &swap_total); + if (ret < 0) { + _E("failed to get system SWAP total memory\n"); + return -EINVAL; + } + } + + *val = swap_total; + + return 0; +} + static int memory_get_memory_info(const struct resource *res, const struct resource_attribute *attr, void *data) @@ -89,6 +108,12 @@ static int memory_get_memory_info(const struct resource *res, case MEMORY_ATTR_CMA_FREE: ret = kernel_get_memory_info(PROC_MEM_INFO_CMA_FREE, val); break; + case MEMORY_ATTR_SWAP_TOTAL: + ret = memory_get_swap_total(val); + break; + case MEMORY_ATTR_SWAP_FREE: + ret = kernel_get_memory_info(PROC_MEM_INFO_SWAP_FREE, val); + break; default: _E("wrong memory resource attribute\n"); ret = -EINVAL; @@ -149,6 +174,20 @@ static const struct resource_attribute memory_attrs[] = { .ops = { .get = memory_get_memory_info, } + }, { + .name = "MEMORY_ATTR_SWAP_TOTAL", + .id = MEMORY_ATTR_SWAP_TOTAL, + .type = DATA_TYPE_UINT64, + .ops = { + .get = memory_get_memory_info, + } + }, { + .name = "MEMORY_ATTR_SWAP_FREE", + .id = MEMORY_ATTR_SWAP_FREE, + .type = DATA_TYPE_UINT64, + .ops = { + .get = memory_get_memory_info, + } }, }; -- 2.7.4 From 5e3193730bd2a1095da2e792341f6940decc2541 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 17 Jun 2022 15:04:56 +0900 Subject: [PATCH 13/16] packaging: Remove unnecessary symlink in sockets.target.wants After removing pass.socket, symlink to it in sockets.target.wants remains. Remove unnecessary symlink. This removes next packaging warning message: warning: Installed (but unpackaged) file(s) found: /usr/lib/systemd/system/sockets.target.wants/pass.socket Change-Id: I8f02dc5d83d8ecd41cf4c3e440b8eeb917bb0aee Fixes: commit 00a3aedc ("pass: Remove unused pass.socket file") Signed-off-by: Seung-Woo Kim --- packaging/pass.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/packaging/pass.spec b/packaging/pass.spec index a9820c8..7c64eae 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -89,7 +89,6 @@ rm -rf %{buildroot} %make_install %install_service delayed.target.wants %{daemon_name}.service -%install_service sockets.target.wants %{daemon_name}.socket %post -- 2.7.4 From 22c73d2d9e34d64bca4e4d2b69f2ebbf685271ed Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 17 Jun 2022 15:15:15 +0900 Subject: [PATCH 14/16] pass: Remove unnecessary installed service files The dbus activation service files are not necessary in systemd unitdir. Remove unnecessary installation of dbus activation service files. This removes below packaging warning message: warning: Installed (but unpackaged) file(s) found: /usr/lib/systemd/system/org.tizen.system.pass.service /usr/lib/systemd/system/org.tizen.system.thermal.service Change-Id: I5c13e31032b07db7ac11271ad5f231737383b0f8 Fixes: commit d0b00031fc66 ("core: Add support for dbus activation for thermal") Fixes: commit da1dc2ab2a66 ("core: Apply systemd-based dbus activation") Signed-off-by: Seung-Woo Kim --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba83e67..517d855 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.thermal.service DESTI INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/systemd/ DESTINATION lib/systemd/system FILES_MATCHING - PATTERN "*.service" + PATTERN "${PROJECT_NAME}.service" ) ADD_SUBDIRECTORY(unittest) -- 2.7.4 From b9f08a7f088b274b8018d7ac34b2f74a45dcad9e Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 12 May 2022 14:44:33 +0900 Subject: [PATCH 15/16] util: kernel: Add functions for getting process smaps file Change-Id: Id8b9d677585ccc4381c33eb53373037c64540f59 Signed-off-by: Dongwoo Lee --- include/util/kernel.h | 8 ++++++++ src/util/kernel.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/util/kernel.h b/include/util/kernel.h index 5938d9f..c640bd5 100644 --- a/include/util/kernel.h +++ b/include/util/kernel.h @@ -35,6 +35,13 @@ struct cpu_stat { int64_t soft_irq; }; +struct proc_map_info { + uint32_t rss; + uint32_t pss; + uint32_t swap; + uint32_t swap_pss; +}; + enum { PROCESS_STAT_FIELD_PID, PROCESS_STAT_FIELD_COMM, @@ -58,4 +65,5 @@ int kernel_get_process_stat_fields(pid_t pid, char *buffer, int buf_len, char *stat_fields[PROCESS_STAT_FIELD_MAX]); int kernel_get_process_taskstats(struct taskstats *stats, int cmd_type, pid_t pid); int kernel_get_thread_group_taskstats(struct taskstats *stats, pid_t tgid, bool get_proc_info); +int kernel_get_thread_group_map_info(struct proc_map_info *map_info, pid_t tgid); #endif diff --git a/src/util/kernel.c b/src/util/kernel.c index 653b297..2101535 100644 --- a/src/util/kernel.c +++ b/src/util/kernel.c @@ -27,6 +27,8 @@ #include #include +static int have_smaps_rollup; + static int __get_cpu_num(char *path) { FILE *fp; @@ -407,3 +409,44 @@ int kernel_get_thread_group_taskstats(struct taskstats *stats, pid_t tgid, bool return 0; } + +int kernel_get_thread_group_map_info(struct proc_map_info *map_info, pid_t tgid) +{ + char smap_file_path[BUFF_MAX]; + char buffer[BUFF_MAX]; + FILE *smaps_file; + + sprintf(smap_file_path, "/proc/%d/%s", tgid, have_smaps_rollup ? "smaps_rollup" : "smaps"); + + smaps_file = fopen(smap_file_path, "r"); + if (!smaps_file) + return -EIO; + + map_info->rss = 0; + map_info->pss = 0; + map_info->swap = 0; + map_info->swap_pss = 0; + + while (fgets(buffer, sizeof(buffer), smaps_file)) { + if (strchr(buffer, '\n') == 0) + continue; + + if (strstr(buffer, "Rss:")) + map_info->rss += strtol(buffer + 4, NULL, 10); + else if (strstr(buffer, "Pss:")) + map_info->pss += strtol(buffer + 4, NULL, 10); + else if (strstr(buffer, "Swap:")) + map_info->swap += strtol(buffer + 5, NULL, 10); + else if (strstr(buffer, "SwapPss:")) + map_info->swap_pss += strtol(buffer + 8, NULL, 10); + } + + fclose(smaps_file); + + return 0; +} + +static void __CONSTRUCTOR__ kernel_init(void) +{ + have_smaps_rollup = !access("/proc/self/smaps_rollup", R_OK); +} -- 2.7.4 From 0c15611cbf696b7fb212e8f37a97b6b35dcb10d4 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 17 Jun 2022 18:03:11 +0900 Subject: [PATCH 16/16] tests: Move test code into tests directory and redefine the test role Move test code into tests directory and redefine the test role as following because unittest will be added for each module. - intergraion test : Test the public interface of PASS daemon - haltest : Test the HAL interface of PASS daemon Change-Id: Ief0d07b38491454dc0dbb06a268e5c56de31a886 Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 5 +-- packaging/pass.spec | 2 +- {unittest => tests/haltest}/CMakeLists.txt | 9 +----- {unittest => tests/haltest}/power-haltests.cpp | 0 tests/integration-test/CMakeLists.txt | 37 ++++++++++++++++++++++ .../integration-test/pass-tests.cpp | 0 6 files changed, 42 insertions(+), 11 deletions(-) rename {unittest => tests/haltest}/CMakeLists.txt (73%) rename {unittest => tests/haltest}/power-haltests.cpp (100%) create mode 100644 tests/integration-test/CMakeLists.txt rename unittest/pass-unittests.cpp => tests/integration-test/pass-tests.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 517d855..6116b46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(pass C) +PROJECT(pass) ######################################################## # PASS CMakeLists.txt @@ -130,5 +130,6 @@ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/systemd/ DESTINATION lib/systemd/s PATTERN "${PROJECT_NAME}.service" ) -ADD_SUBDIRECTORY(unittest) +ADD_SUBDIRECTORY(tests/integration-test) +ADD_SUBDIRECTORY(tests/haltest) ADD_SUBDIRECTORY(lib) diff --git a/packaging/pass.spec b/packaging/pass.spec index 7c64eae..29a506e 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -123,7 +123,7 @@ systemctl daemon-reload %files -n %{unittest_name} %defattr(-,root,root,-) -%{_bindir}/pass-unittests +%{_bindir}/pass-tests %files -n %{libpass_resource_monitor_name} %license LICENSE diff --git a/unittest/CMakeLists.txt b/tests/haltest/CMakeLists.txt similarity index 73% rename from unittest/CMakeLists.txt rename to tests/haltest/CMakeLists.txt index 802fa58..1f0e9a3 100644 --- a/unittest/CMakeLists.txt +++ b/tests/haltest/CMakeLists.txt @@ -29,16 +29,9 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") -SET(src ${CMAKE_SOURCE_DIR}/unittest/power-haltests.cpp) +SET(src ${CMAKE_SOURCE_DIR}/tests/haltest/power-haltests.cpp) GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) MESSAGE("${src_name}") ADD_EXECUTABLE(${src_name} ${SRCS} ${src}) TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal) INSTALL(TARGETS ${src_name} DESTINATION /usr/bin/hal) - -SET(src ${CMAKE_SOURCE_DIR}/unittest/pass-unittests.cpp) -GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) -MESSAGE("${src_name}") -ADD_EXECUTABLE(${src_name} ${SRCS} ${src}) -TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal) -INSTALL(TARGETS ${src_name} DESTINATION /usr/bin/) diff --git a/unittest/power-haltests.cpp b/tests/haltest/power-haltests.cpp similarity index 100% rename from unittest/power-haltests.cpp rename to tests/haltest/power-haltests.cpp diff --git a/tests/integration-test/CMakeLists.txt b/tests/integration-test/CMakeLists.txt new file mode 100644 index 0000000..2f12af5 --- /dev/null +++ b/tests/integration-test/CMakeLists.txt @@ -0,0 +1,37 @@ +PROJECT(pass C CXX) + +SET(SRCS ${CMAKE_SOURCE_DIR}/src/pass/pass-hal.c + ${CMAKE_SOURCE_DIR}/src/pass/pass-parser.c + ${CMAKE_SOURCE_DIR}/src/util/common.c +) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/pass) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(gtest_pkgs REQUIRED + glib-2.0 + gio-2.0 + gmock + dlog + json-c + hal-api-power +) + +FOREACH(flag ${gtest_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall -fPIE -fPIC") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") + +SET(src ${CMAKE_SOURCE_DIR}/tests/integration-test/pass-tests.cpp) +GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) +MESSAGE("${src_name}") +ADD_EXECUTABLE(${src_name} ${SRCS} ${src}) +TARGET_LINK_LIBRARIES(${src_name} ${gtest_LDFLAGS} ${gtest_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal) +INSTALL(TARGETS ${src_name} DESTINATION /usr/bin/) diff --git a/unittest/pass-unittests.cpp b/tests/integration-test/pass-tests.cpp similarity index 100% rename from unittest/pass-unittests.cpp rename to tests/integration-test/pass-tests.cpp -- 2.7.4