1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-24 21:34:08 +03:00

bootchart: Account CPU time spent in non-main threads of processes (v5)

Fix for issue https://github.com/systemd/systemd/issues/139

- Implement fixes suggested by @teg to -v2
- Implement fixes suggested by @zonque to -v3 and -v4
This commit is contained in:
Gianpaolo Macario 2015-06-11 10:03:30 +00:00 committed by Gianpaolo Macario
parent 9ebdb1e057
commit caa4339784

View File

@ -115,6 +115,7 @@ int log_sample(DIR *proc,
struct list_sample_data *sampledata;
struct ps_sched_struct *ps_prev = NULL;
int procfd;
int taskfd = -1;
sampledata = *ptr;
@ -409,6 +410,63 @@ schedstat_next:
ps->total = (ps->last->runtime - ps->first->runtime)
/ 1000000000.0;
/* Take into account CPU runtime/waittime spent in non-main threads of the process
* by parsing "/proc/[pid]/task/[tid]/schedstat" for all [tid] != [pid]
* See https://github.com/systemd/systemd/issues/139
*/
/* Browse directory "/proc/[pid]/task" to know the thread ids of process [pid] */
snprintf(filename, sizeof(filename), PID_FMT "/task", pid);
taskfd = openat(procfd, filename, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
if (taskfd >= 0) {
_cleanup_closedir_ DIR *taskdir = NULL;
taskdir = fdopendir(taskfd);
if (!taskdir) {
safe_close(taskfd);
return -errno;
}
FOREACH_DIRENT(ent, taskdir, break) {
int r;
int tid = -1;
_cleanup_close_ int tid_schedstat = -1;
long long delta_rt;
long long delta_wt;
if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9'))
continue;
/* Skip main thread as it was already accounted */
r = safe_atoi(ent->d_name, &tid);
if (r < 0 || tid == pid)
continue;
/* Parse "/proc/[pid]/task/[tid]/schedstat" */
snprintf(filename, sizeof(filename), PID_FMT "/schedstat", tid);
tid_schedstat = openat(taskfd, filename, O_RDONLY|O_CLOEXEC);
if (tid_schedstat == -1)
continue;
s = pread(tid_schedstat, buf, sizeof(buf) - 1, 0);
if (s <= 0)
continue;
buf[s] = '\0';
if (!sscanf(buf, "%s %s %*s", rt, wt))
continue;
r = safe_atolli(rt, &delta_rt);
if (r < 0)
continue;
r = safe_atolli(rt, &delta_wt);
if (r < 0)
continue;
ps->sample->runtime += delta_rt;
ps->sample->waittime += delta_wt;
}
}
if (!arg_pss)
goto catch_rename;