#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;
};
{
struct process_group_context *ctx;
struct array_value *list = data;
- struct process_info *pi;
+ struct process_info_node *node;
int *data_array;
int i;
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;
{
struct process_group_context *ctx;
struct array_value *list = data;
- struct process_info *pi;
+ struct process_info_node *node;
char **data_array;
int i;
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]);
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;
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;
}
},
};
+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;
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;
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;
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;
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 = {