diff --git a/ucollection/ucollection_process_cpu.c b/ucollection/ucollection_process_cpu.c index 9b23473ecc0cd12b450f2131eb63ff1c185a2992..206a5dc4792787d563b9a7abf3985d1237842153 100644 --- a/ucollection/ucollection_process_cpu.c +++ b/ucollection/ucollection_process_cpu.c @@ -31,15 +31,6 @@ unsigned long long __attribute__((weak)) get_proc_cpu_load(struct task_struct *t return 0; } -static int get_cpu_num(void) -{ - int core_num = 0; - int i = 0; - for_each_possible_cpu(i) - core_num++; - return core_num; -} - static void get_process_flt(struct task_struct *task, unsigned long long *min_flt, unsigned long long *maj_flt) { unsigned long tmp_min_flt = 0; @@ -80,7 +71,7 @@ static void get_process_usage_cputime(struct task_struct *task, unsigned long lo *st = stime; } -static void get_process_load(struct task_struct *task, int cpu_num, int cur_count, +static void get_process_load(struct task_struct *task, int cur_count, struct ucollection_process_cpu_entry __user *entry) { struct ucollection_process_cpu_item proc_cpu_entry; @@ -92,9 +83,25 @@ static void get_process_load(struct task_struct *task, int cpu_num, int cur_coun (void)copy_to_user(&entry->datas[cur_count], &proc_cpu_entry, sizeof(struct ucollection_process_cpu_item)); } +static void get_thread_load(struct task_struct *task, int cur_count, + struct ucollection_thread_cpu_entry __user *entry) +{ + struct ucollection_thread_cpu_item thread_cpu_item; + memset(&thread_cpu_item, 0, sizeof(struct ucollection_thread_cpu_item)); + unsigned long long utime, stime; + utime = task->utime; + stime = task->stime; + do_div(utime, NS_TO_MS); + do_div(stime, NS_TO_MS); + thread_cpu_item.tid = task->pid; + thread_cpu_item.cpu_usage_utime = utime; + thread_cpu_item.cpu_usage_stime = stime; + thread_cpu_item.cpu_load_time = 0; + (void)copy_to_user(&entry->datas[cur_count], &thread_cpu_item, sizeof(struct ucollection_thread_cpu_item)); +} + static long ioctrl_collect_process_cpu(void __user *argp) { - int cpu_num = 0; struct task_struct *task = NULL; struct ucollection_process_cpu_entry kentry; struct ucollection_process_cpu_entry __user *entry = argp; @@ -106,7 +113,6 @@ static long ioctrl_collect_process_cpu(void __user *argp) memset(&kentry, 0, sizeof(struct ucollection_process_cpu_entry)); (void)copy_from_user(&kentry, entry, sizeof(struct ucollection_process_cpu_entry)); - cpu_num = get_cpu_num(); rcu_read_lock(); task = &init_task; for_each_process(task) { @@ -118,7 +124,7 @@ static long ioctrl_collect_process_cpu(void __user *argp) break; } - get_process_load(task, cpu_num, kentry.cur_count, entry); + get_process_load(task, kentry.cur_count, entry); kentry.cur_count++; } put_user(kentry.cur_count, &entry->cur_count); @@ -136,9 +142,108 @@ static bool is_pid_alive(int pid) return pid_alive(task); } +static long ioctrl_collect_thread_count(void __user *argp) +{ + struct task_struct *task = NULL; + struct ucollection_process_thread_count kcount; + struct ucollection_process_thread_count __user *count = argp; + if (count == NULL) { + pr_err("cpu entry is null"); + return -EINVAL; + } + memset(&kcount, 0, sizeof(struct ucollection_process_thread_count)); + (void)copy_from_user(&kcount, count, sizeof(struct ucollection_process_thread_count)); + rcu_read_lock(); + if (!is_pid_alive(kcount.pid)) { + pr_err("pid=%d is not alive", kcount.pid); + rcu_read_unlock(); + return -EINVAL; + } + task = find_task_by_vpid(kcount.pid); + if (task == NULL) { + pr_err("can not get pid=%d", task->pid); + rcu_read_unlock(); + return -EINVAL; + } + uint32_t thread_count = 0; + struct task_struct *t = task; + do { + thread_count++; + } while_each_thread(task, t); + put_user(thread_count, &count->thread_count); + rcu_read_unlock(); + return 0; +} + +static long read_thread_info_locked(struct ucollection_thread_cpu_entry *kentry, + struct ucollection_thread_cpu_entry __user *entry) +{ + rcu_read_lock(); + if (!is_pid_alive(kentry->filter.pid)) { + pr_err("pid=%d is not alive", kentry->filter.pid); + rcu_read_unlock(); + return -EINVAL; + } + struct task_struct *task = NULL; + task = find_task_by_vpid(kentry->filter.pid); + if (task == NULL) { + pr_err("can not get pid=%d", task->pid); + rcu_read_unlock(); + return -EINVAL; + } + uint32_t thread_count = 0; + struct task_struct *t = task; + do { + if (thread_count >= kentry->total_count) { + pr_err("thread over total count"); + break; + } + get_thread_load(t, thread_count, entry); + thread_count++; + } while_each_thread(task, t); + put_user(thread_count, &entry->cur_count); + rcu_read_unlock(); + return 0; +} + +static long ioctrl_collect_app_thread_cpu(void __user *argp) +{ + struct ucollection_thread_cpu_entry kentry; + struct ucollection_thread_cpu_entry __user *entry = argp; + if (entry == NULL) { + pr_err("cpu entry is null"); + return -EINVAL; + } + memset(&kentry, 0, sizeof(struct ucollection_thread_cpu_entry)); + (void)copy_from_user(&kentry, entry, sizeof(struct ucollection_thread_cpu_entry)); + if (current->pid != kentry.filter.pid || kentry.cur_count >= kentry.total_count) { + pr_err("pid=%d is not self current:%d , or current count over total count" + , kentry.filter.pid, current->pid); + return -EINVAL; + } + return read_thread_info_locked(&kentry, entry); +} + +static long ioctrl_collect_the_thread_cpu(void __user *argp) +{ + struct ucollection_thread_cpu_entry kentry; + struct ucollection_thread_cpu_entry __user *entry = argp; + if (entry == NULL) { + pr_err("cpu entry is null"); + return -EINVAL; + } + memset(&kentry, 0, sizeof(struct ucollection_thread_cpu_entry)); + (void)copy_from_user(&kentry, entry, sizeof(struct ucollection_thread_cpu_entry)); + if (kentry.cur_count >= kentry.total_count) { + pr_err("pid=%d is not self current:%d , or current count over total count" + , kentry.filter.pid, current->pid); + return -EINVAL; + } + return read_thread_info_locked(&kentry, entry); +} + static long ioctrl_collect_the_process_cpu(void __user *argp) { - int cpu_num = 0; struct task_struct *task = NULL; struct ucollection_process_cpu_entry kentry; struct ucollection_process_cpu_entry __user *entry = argp; @@ -169,31 +274,13 @@ static long ioctrl_collect_the_process_cpu(void __user *argp) return -EINVAL; } - cpu_num = get_cpu_num(); - get_process_load(task, cpu_num, kentry.cur_count, entry); + get_process_load(task, kentry.cur_count, entry); kentry.cur_count++; put_user(kentry.cur_count, &entry->cur_count); rcu_read_unlock(); return 0; } -static long ioctrl_set_cpu_dmips(void __user *argp) -{ - int i; - struct ucollection_cpu_dmips kentry; - struct ucollection_cpu_dmips __user *entry = argp; - memset(&kentry, 0, sizeof(struct ucollection_cpu_dmips)); - (void)copy_from_user(&kentry, entry, sizeof(struct ucollection_cpu_dmips)); - pr_info("set dimps %d cpus\n", kentry.total_count); - for (i = 0; i < DMIPS_NUM; i++) { - if (i >= kentry.total_count) - break; - get_user(dmips_values[i], &entry->dmips[i]); - pr_info("set dimps cpu[%d]=%d\n", i, dmips_values[i]); - } - return 0; -} - long unified_collection_collect_process_cpu(unsigned int cmd, void __user *argp) { long ret = 0; @@ -204,8 +291,14 @@ long unified_collection_collect_process_cpu(unsigned int cmd, void __user *argp) case IOCTRL_COLLECT_THE_PROC_CPU: ret = ioctrl_collect_the_process_cpu(argp); break; - case IOCTRL_SET_CPU_DMIPS: - ret = ioctrl_set_cpu_dmips(argp); + case IOCTRL_COLLECT_THREAD_COUNT: + ret = ioctrl_collect_thread_count(argp); + break; + case IOCTRL_COLLECT_APP_THREAD: + ret = ioctrl_collect_app_thread_cpu(argp); + break; + case IOCTRL_COLLECT_THE_THREAD: + ret = ioctrl_collect_the_thread_cpu(argp); break; default: pr_err("handle ioctrl cmd %u, _IOC_TYPE(cmd)=%d", cmd, _IOC_TYPE(cmd)); diff --git a/ucollection/unified_collection_data.h b/ucollection/unified_collection_data.h index 2f3773f055936ce9eee6d533afe93cc7073ec223..faf9a699f91aac06888eb5085c84b6cdd4262104 100644 --- a/ucollection/unified_collection_data.h +++ b/ucollection/unified_collection_data.h @@ -31,19 +31,50 @@ struct ucollection_process_cpu_entry { struct ucollection_process_cpu_item datas[]; }; -struct ucollection_cpu_dmips { - int magic; - int total_count; - char dmips[]; +struct ucollection_process_thread_count { + uint32_t pid; + uint32_t thread_count; }; -#define IOCTRL_COLLECT_ALL_PROC_CPU_MAGIC 1 -#define IOCTRL_COLLECT_THE_PROC_CPU_MAGIC 1 -#define IOCTRL_SET_CPU_DMIPS_MAGIC 1 -#define DMIPS_NUM 128 +struct ucollection_thread_cpu_item { + int tid; + unsigned long long cpu_usage_utime; + unsigned long long cpu_usage_stime; + unsigned long long cpu_load_time; +}; + +struct ucollection_thread_filter { + int uid; + int pid; + int tid; +}; +struct ucollection_thread_cpu_entry { + int magic; + unsigned int total_count; + unsigned int cur_count; + struct ucollection_thread_filter filter; + struct ucollection_thread_cpu_item datas[]; +}; + +enum collection_type { + COLLECT_ALL_PROC = 1, + COLLECT_THE_PROC, + COLLECT_APP_PROC, + COLLECT_PROC_COUNT, + COLLECT_THREAD_COUNT, + COLLECT_APP_THREAD, + COLLECT_THE_THREAD, +}; + +#define DMIPS_NUM 128 #define IOCTRL_COLLECT_CPU_BASE 0 -#define IOCTRL_COLLECT_ALL_PROC_CPU _IOR(IOCTRL_COLLECT_CPU_BASE, 1, struct ucollection_process_cpu_entry) -#define IOCTRL_COLLECT_THE_PROC_CPU _IOR(IOCTRL_COLLECT_CPU_BASE, 2, struct ucollection_process_cpu_entry) -#define IOCTRL_SET_CPU_DMIPS _IOW(IOCTRL_COLLECT_CPU_BASE, 3, struct ucollection_cpu_dmips) +#define IOCTRL_COLLECT_ALL_PROC_CPU _IOR(IOCTRL_COLLECT_CPU_BASE, COLLECT_ALL_PROC, \ + struct ucollection_process_cpu_entry) +#define IOCTRL_COLLECT_THE_PROC_CPU _IOR(IOCTRL_COLLECT_CPU_BASE, COLLECT_THE_PROC, \ + struct ucollection_process_cpu_entry) +#define IOCTRL_COLLECT_THREAD_COUNT _IOR(IOCTRL_COLLECT_CPU_BASE, COLLECT_THREAD_COUNT, \ + struct ucollection_process_thread_count) +#define IOCTRL_COLLECT_APP_THREAD _IOR(IOCTRL_COLLECT_CPU_BASE, COLLECT_APP_THREAD, struct ucollection_thread_cpu_entry) +#define IOCTRL_COLLECT_THE_THREAD _IOR(IOCTRL_COLLECT_CPU_BASE, COLLECT_THE_THREAD, struct ucollection_thread_cpu_entry) #endif // __UNIFIED_COLLECTION_DATA__ \ No newline at end of file