static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) { struct per_pid *p = NULL, *prev_p; struct sched_switch *sw = (void *)te; prev_p = find_create_pid(sw->prev_pid); p = find_create_pid(sw->next_pid); if (prev_p->current && prev_p->current->state != TYPE_NONE) pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu, prev_p->current->state_since, timestamp); if (p && p->current) { if (p->current->state != TYPE_NONE) pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp); p->current->state_since = timestamp; p->current->state = TYPE_RUNNING; } if (prev_p->current) { prev_p->current->state = TYPE_NONE; prev_p->current->state_since = timestamp; if (sw->prev_state & 2) prev_p->current->state = TYPE_BLOCKED; if (sw->prev_state == 0) prev_p->current->state = TYPE_WAITING; } }
static void pid_fork(int pid, int ppid, u64 timestamp) { struct per_pid *p, *pp; p = find_create_pid(pid); pp = find_create_pid(ppid); p->ppid = ppid; if (pp->current && pp->current->comm && !p->current) pid_set_comm(pid, pp->current->comm); p->start_time = timestamp; if (p->current) { p->current->start_time = timestamp; p->current->state_since = timestamp; } }
static void pid_set_comm(int pid, char *comm) { struct per_pid *p; struct per_pidcomm *c; p = find_create_pid(pid); c = p->all; while (c) { if (c->comm && strcmp(c->comm, comm) == 0) { p->current = c; return; } if (!c->comm) { c->comm = strdup(comm); p->current = c; return; } c = c->next; } c = malloc(sizeof(struct per_pidcomm)); assert(c != NULL); memset(c, 0, sizeof(struct per_pidcomm)); c->comm = strdup(comm); p->current = c; c->next = p->all; p->all = c; }
static void sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te) { struct wake_event *we; struct per_pid *p; struct wakeup_entry *wake = (void *)te; we = malloc(sizeof(struct wake_event)); if (!we) return; memset(we, 0, sizeof(struct wake_event)); we->time = timestamp; we->waker = pid; if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ)) we->waker = -1; we->wakee = wake->pid; we->next = wake_events; wake_events = we; p = find_create_pid(we->wakee); if (p && p->current && p->current->state == TYPE_NONE) { p->current->state_since = timestamp; p->current->state = TYPE_WAITING; } if (p && p->current && p->current->state == TYPE_BLOCKED) { pid_put_sample(p->pid, p->current->state, cpu, p->current->state_since, timestamp); p->current->state_since = timestamp; p->current->state = TYPE_WAITING; } }
static void pid_exit(int pid, u64 timestamp) { struct per_pid *p; p = find_create_pid(pid); p->end_time = timestamp; if (p->current) p->current->end_time = timestamp; }
static void pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end) { struct per_pid *p; struct per_pidcomm *c; struct cpu_sample *sample; p = find_create_pid(pid); c = p->current; if (!c) { c = malloc(sizeof(struct per_pidcomm)); assert(c != NULL); memset(c, 0, sizeof(struct per_pidcomm)); p->current = c; c->next = p->all; p->all = c; } sample = malloc(sizeof(struct cpu_sample)); assert(sample != NULL); memset(sample, 0, sizeof(struct cpu_sample)); sample->start_time = start; sample->end_time = end; sample->type = type; sample->next = c->samples; sample->cpu = cpu; c->samples = sample; if (sample->type == TYPE_RUNNING && end > start && start > 0) { c->total_time += (end-start); p->total_time += (end-start); } if (c->start_time == 0 || c->start_time > start) c->start_time = start; if (p->start_time == 0 || p->start_time > start) p->start_time = start; if (cpu > numcpus) numcpus = cpu; }
static void pid_put_sample(struct timechart *tchart, int pid, int type, unsigned int cpu, u64 start, u64 end, const char *backtrace) { struct per_pid *p; struct per_pidcomm *c; struct cpu_sample *sample; p = find_create_pid(tchart, pid); c = p->current; if (!c) { c = zalloc(sizeof(*c)); assert(c != NULL); p->current = c; c->next = p->all; p->all = c; } sample = zalloc(sizeof(*sample)); assert(sample != NULL); sample->start_time = start; sample->end_time = end; sample->type = type; sample->next = c->samples; sample->cpu = cpu; sample->backtrace = backtrace; c->samples = sample; if (sample->type == TYPE_RUNNING && end > start && start > 0) { c->total_time += (end-start); p->total_time += (end-start); } if (c->start_time == 0 || c->start_time > start) c->start_time = start; if (p->start_time == 0 || p->start_time > start) p->start_time = start; }