⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trace.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct trace_array_cpu *data = iter->tr->data[iter->cpu];	data->trace_tail_idx++;	if (data->trace_tail_idx >= ENTRIES_PER_PAGE) {		data->trace_tail = trace_next_page(data, data->trace_tail);		data->trace_tail_idx = 0;	}	/* Check if we empty it, then reset the index */	if (data->trace_head == data->trace_tail &&	    data->trace_head_idx == data->trace_tail_idx)		data->trace_idx = 0;}static void *find_next_entry_inc(struct trace_iterator *iter){	struct trace_entry *next;	int next_cpu = -1;	next = find_next_entry(iter, &next_cpu);	iter->prev_ent = iter->ent;	iter->prev_cpu = iter->cpu;	iter->ent = next;	iter->cpu = next_cpu;	if (next)		trace_iterator_increment(iter);	return next ? iter : NULL;}static void *s_next(struct seq_file *m, void *v, loff_t *pos){	struct trace_iterator *iter = m->private;	int i = (int)*pos;	void *ent;	(*pos)++;	/* can't go backwards */	if (iter->idx > i)		return NULL;	if (iter->idx < 0)		ent = find_next_entry_inc(iter);	else		ent = iter;	while (ent && iter->idx < i)		ent = find_next_entry_inc(iter);	iter->pos = *pos;	return ent;}static void *s_start(struct seq_file *m, loff_t *pos){	struct trace_iterator *iter = m->private;	void *p = NULL;	loff_t l = 0;	int i;	mutex_lock(&trace_types_lock);	if (!current_trace || current_trace != iter->trace) {		mutex_unlock(&trace_types_lock);		return NULL;	}	atomic_inc(&trace_record_cmdline_disabled);	/* let the tracer grab locks here if needed */	if (current_trace->start)		current_trace->start(iter);	if (*pos != iter->pos) {		iter->ent = NULL;		iter->cpu = 0;		iter->idx = -1;		iter->prev_ent = NULL;		iter->prev_cpu = -1;		for_each_tracing_cpu(i) {			iter->next_idx[i] = 0;			iter->next_page[i] = NULL;		}		for (p = iter; p && l < *pos; p = s_next(m, p, &l))			;	} else {		l = *pos - 1;		p = s_next(m, p, &l);	}	return p;}static void s_stop(struct seq_file *m, void *p){	struct trace_iterator *iter = m->private;	atomic_dec(&trace_record_cmdline_disabled);	/* let the tracer release locks here if needed */	if (current_trace && current_trace == iter->trace && iter->trace->stop)		iter->trace->stop(iter);	mutex_unlock(&trace_types_lock);}#define KRETPROBE_MSG "[unknown/kretprobe'd]"#ifdef CONFIG_KRETPROBESstatic inline int kretprobed(unsigned long addr){	return addr == (unsigned long)kretprobe_trampoline;}#elsestatic inline int kretprobed(unsigned long addr){	return 0;}#endif /* CONFIG_KRETPROBES */static intseq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address){#ifdef CONFIG_KALLSYMS	char str[KSYM_SYMBOL_LEN];	kallsyms_lookup(address, NULL, NULL, NULL, str);	return trace_seq_printf(s, fmt, str);#endif	return 1;}static intseq_print_sym_offset(struct trace_seq *s, const char *fmt,		     unsigned long address){#ifdef CONFIG_KALLSYMS	char str[KSYM_SYMBOL_LEN];	sprint_symbol(str, address);	return trace_seq_printf(s, fmt, str);#endif	return 1;}#ifndef CONFIG_64BIT# define IP_FMT "%08lx"#else# define IP_FMT "%016lx"#endifstatic intseq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags){	int ret;	if (!ip)		return trace_seq_printf(s, "0");	if (sym_flags & TRACE_ITER_SYM_OFFSET)		ret = seq_print_sym_offset(s, "%s", ip);	else		ret = seq_print_sym_short(s, "%s", ip);	if (!ret)		return 0;	if (sym_flags & TRACE_ITER_SYM_ADDR)		ret = trace_seq_printf(s, " <" IP_FMT ">", ip);	return ret;}static void print_lat_help_header(struct seq_file *m){	seq_puts(m, "#                _------=> CPU#            \n");	seq_puts(m, "#               / _-----=> irqs-off        \n");	seq_puts(m, "#              | / _----=> need-resched    \n");	seq_puts(m, "#              || / _---=> hardirq/softirq \n");	seq_puts(m, "#              ||| / _--=> preempt-depth   \n");	seq_puts(m, "#              |||| /                      \n");	seq_puts(m, "#              |||||     delay             \n");	seq_puts(m, "#  cmd     pid ||||| time  |   caller      \n");	seq_puts(m, "#     \\   /    |||||   \\   |   /           \n");}static void print_func_help_header(struct seq_file *m){	seq_puts(m, "#           TASK-PID   CPU#    TIMESTAMP  FUNCTION\n");	seq_puts(m, "#              | |      |          |         |\n");}static voidprint_trace_header(struct seq_file *m, struct trace_iterator *iter){	unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);	struct trace_array *tr = iter->tr;	struct trace_array_cpu *data = tr->data[tr->cpu];	struct tracer *type = current_trace;	unsigned long total   = 0;	unsigned long entries = 0;	int cpu;	const char *name = "preemption";	if (type)		name = type->name;	for_each_tracing_cpu(cpu) {		if (head_page(tr->data[cpu])) {			total += tr->data[cpu]->trace_idx;			if (tr->data[cpu]->trace_idx > tr->entries)				entries += tr->entries;			else				entries += tr->data[cpu]->trace_idx;		}	}	seq_printf(m, "%s latency trace v1.1.5 on %s\n",		   name, UTS_RELEASE);	seq_puts(m, "-----------------------------------"		 "---------------------------------\n");	seq_printf(m, " latency: %lu us, #%lu/%lu, CPU#%d |"		   " (M:%s VP:%d, KP:%d, SP:%d HP:%d",		   nsecs_to_usecs(data->saved_latency),		   entries,		   total,		   tr->cpu,#if defined(CONFIG_PREEMPT_NONE)		   "server",#elif defined(CONFIG_PREEMPT_VOLUNTARY)		   "desktop",#elif defined(CONFIG_PREEMPT)		   "preempt",#else		   "unknown",#endif		   /* These are reserved for later use */		   0, 0, 0, 0);#ifdef CONFIG_SMP	seq_printf(m, " #P:%d)\n", num_online_cpus());#else	seq_puts(m, ")\n");#endif	seq_puts(m, "    -----------------\n");	seq_printf(m, "    | task: %.16s-%d "		   "(uid:%d nice:%ld policy:%ld rt_prio:%ld)\n",		   data->comm, data->pid, data->uid, data->nice,		   data->policy, data->rt_priority);	seq_puts(m, "    -----------------\n");	if (data->critical_start) {		seq_puts(m, " => started at: ");		seq_print_ip_sym(&iter->seq, data->critical_start, sym_flags);		trace_print_seq(m, &iter->seq);		seq_puts(m, "\n => ended at:   ");		seq_print_ip_sym(&iter->seq, data->critical_end, sym_flags);		trace_print_seq(m, &iter->seq);		seq_puts(m, "\n");	}	seq_puts(m, "\n");}static voidlat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu){	int hardirq, softirq;	char *comm;	comm = trace_find_cmdline(entry->pid);	trace_seq_printf(s, "%8.8s-%-5d ", comm, entry->pid);	trace_seq_printf(s, "%d", cpu);	trace_seq_printf(s, "%c%c",			(entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : '.',			((entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.'));	hardirq = entry->flags & TRACE_FLAG_HARDIRQ;	softirq = entry->flags & TRACE_FLAG_SOFTIRQ;	if (hardirq && softirq) {		trace_seq_putc(s, 'H');	} else {		if (hardirq) {			trace_seq_putc(s, 'h');		} else {			if (softirq)				trace_seq_putc(s, 's');			else				trace_seq_putc(s, '.');		}	}	if (entry->preempt_count)		trace_seq_printf(s, "%x", entry->preempt_count);	else		trace_seq_puts(s, ".");}unsigned long preempt_mark_thresh = 100;static voidlat_print_timestamp(struct trace_seq *s, unsigned long long abs_usecs,		    unsigned long rel_usecs){	trace_seq_printf(s, " %4lldus", abs_usecs);	if (rel_usecs > preempt_mark_thresh)		trace_seq_puts(s, "!: ");	else if (rel_usecs > 1)		trace_seq_puts(s, "+: ");	else		trace_seq_puts(s, " : ");}static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;static intprint_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu){	struct trace_seq *s = &iter->seq;	unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);	struct trace_entry *next_entry = find_next_entry(iter, NULL);	unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);	struct trace_entry *entry = iter->ent;	unsigned long abs_usecs;	unsigned long rel_usecs;	char *comm;	int S, T;	int i;	unsigned state;	if (!next_entry)		next_entry = entry;	rel_usecs = ns2usecs(next_entry->t - entry->t);	abs_usecs = ns2usecs(entry->t - iter->tr->time_start);	if (verbose) {		comm = trace_find_cmdline(entry->pid);		trace_seq_printf(s, "%16s %5d %d %d %08x %08x [%08lx]"				 " %ld.%03ldms (+%ld.%03ldms): ",				 comm,				 entry->pid, cpu, entry->flags,				 entry->preempt_count, trace_idx,				 ns2usecs(entry->t),				 abs_usecs/1000,				 abs_usecs % 1000, rel_usecs/1000,				 rel_usecs % 1000);	} else {		lat_print_generic(s, entry, cpu);		lat_print_timestamp(s, abs_usecs, rel_usecs);	}	switch (entry->type) {	case TRACE_FN:		seq_print_ip_sym(s, entry->fn.ip, sym_flags);		trace_seq_puts(s, " (");		if (kretprobed(entry->fn.parent_ip))			trace_seq_puts(s, KRETPROBE_MSG);		else			seq_print_ip_sym(s, entry->fn.parent_ip, sym_flags);		trace_seq_puts(s, ")\n");		break;	case TRACE_CTX:	case TRACE_WAKE:		T = entry->ctx.next_state < sizeof(state_to_char) ?			state_to_char[entry->ctx.next_state] : 'X';		state = entry->ctx.prev_state ? __ffs(entry->ctx.prev_state) + 1 : 0;		S = state < sizeof(state_to_char) - 1 ? state_to_char[state] : 'X';		comm = trace_find_cmdline(entry->ctx.next_pid);		trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d:%c %s\n",				 entry->ctx.prev_pid,				 entry->ctx.prev_prio,				 S, entry->type == TRACE_CTX ? "==>" : "  +",				 entry->ctx.next_pid,				 entry->ctx.next_prio,				 T, comm);		break;	case TRACE_SPECIAL:		trace_seq_printf(s, "# %ld %ld %ld\n",				 entry->special.arg1,				 entry->special.arg2,				 entry->special.arg3);		break;	case TRACE_STACK:		for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {			if (i)				trace_seq_puts(s, " <= ");			seq_print_ip_sym(s, entry->stack.caller[i], sym_flags);		}		trace_seq_puts(s, "\n");		break;	default:		trace_seq_printf(s, "Unknown type %d\n", entry->type);	}	return 1;}static int print_trace_fmt(struct trace_iterator *iter){	struct trace_seq *s = &iter->seq;	unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);	struct trace_entry *entry;	unsigned long usec_rem;	unsigned long long t;	unsigned long secs;	char *comm;	int ret;	int S, T;	int i;	entry = iter->ent;	comm = trace_find_cmdline(iter->ent->pid);	t = ns2usecs(entry->t);	usec_rem = do_div(t, 1000000ULL);	secs = (unsigned long)t;	ret = trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid);	if (!ret)		return 0;	ret = trace_seq_printf(s, "[%02d] ", iter->cpu);	if (!ret)		return 0;	ret = trace_seq_printf(s, "%5lu.%06lu: ", secs, usec_rem);	if (!ret)		return 0;	switch (entry->type) {	case TRACE_FN:		ret = seq_print_ip_sym(s, entry->fn.ip, sym_flags);		if (!ret)			return 0;		if ((sym_flags & TRACE_ITER_PRINT_PARENT) &&						entry->fn.parent_ip) {			ret = trace_seq_printf(s, " <-");			if (!ret)				return 0;			if (kretprobed(entry->fn.parent_ip))				ret = trace_seq_puts(s, KRETPROBE_MSG);			else				ret = seq_print_ip_sym(s, entry->fn.parent_ip,						       sym_flags);			if (!ret)				return 0;		}		ret = trace_seq_printf(s, "\n");		if (!ret)			return 0;		break;	case TRACE_CTX:	case TRACE_WAKE:		S = entry->ctx.prev_state < sizeof(state_to_char) ?			state_to_char[entry->ctx.prev_state] : 'X';		T = entry->ctx.next_state < sizeof(state_to_char) ?			state_to_char[entry->ctx.next_state] : 'X';		ret = trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d:%c\n",				       entry->ctx.prev_pid,				       entry->ctx.prev_prio,				       S,				       entry->type == TRACE_CTX ? "==>" : "  +",				       entry->ctx.next_pid,				       entry->ctx.next_prio,				       T);		if (!ret)			return 0;		break;	case TRACE_SPECIAL:		ret = trace_seq_printf(s, "# %ld %ld %ld\n",				 entry->special.arg1,				 entry->special.arg2,				 entry->special.arg3);		if (!ret)			return 0;		break;	case TRACE_STACK:		for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {			if (i) {				ret = trace_seq_puts(s, " <= ");				if (!ret)					return 0;			}			ret = seq_print_ip_sym(s, entry->stack.caller[i],					       sym_flags);			if (!ret)				return 0;		}		ret = trace_seq_puts(s, "\n");		if (!ret)			return 0;		break;	}	return 1;}static int print_raw_fmt(struct trace_iterator *iter){	struct trace_seq *s = &iter->seq;	struct trace_entry *entry;	int ret;	int S, T;	entry = iter->ent;	ret = trace_seq_printf(s, "%d %d %llu ",		entry->pid, iter->cpu, entry->t);	if (!ret)		return 0;	switch (entry->type) {	case TRACE_FN:		ret = trace_seq_printf(s, "%x %x\n",					entry->fn.ip, entry->fn.parent_ip);		if (!ret)			return 0;		break;	case TRACE_CTX:	case TRACE_WAKE:		S = entry->ctx.prev_state < sizeof(state_to_char) ?			state_to_char[entry->ctx.prev_state] : 'X';		T = entry->ctx.next_state < sizeof(state_to_char) ?			state_to_char[entry->ctx.next_state] : 'X';		if (entry->type == TRACE_WAKE)			S = '+';		ret = trace_seq_printf(s, "%d %d %c %d %d %c\n",				       entry->ctx.prev_pid,				       entry->ctx.prev_prio,				       S,				       entry->ctx.next_pid,				       entry->ctx.next_prio,				       T);		if (!ret)			return 0;		break;	case TRACE_SPECIAL:	case TRACE_STACK:		ret = trace_seq_printf(s, "# %ld %ld %ld\n",				 entry->special.arg1,				 entry->special.arg2,				 entry->special.arg3);		if (!ret)			return 0;		break;	}	return 1;}#define SEQ_PUT_FIELD_RET(s, x)				\do {							\	if (!trace_seq_putmem(s, &(x), sizeof(x)))	\		return 0;				\} while (0)#define SEQ_PUT_HEX_FIELD_RET(s, x)			\do {							\	if (!trace_seq_putmem_hex(s, &(x), sizeof(x)))	\		return 0;				\} while (0)static int print_hex_fmt(struct trace_iterator *iter){	struct trace_seq *s = &iter->seq;	unsigned char newline = '\n';	struct trace_entry *entry;	int S, T;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -