/*
 * Collect the trace on the current cpu and write it into the ftrace buffer.
 *
 * pre: bts_tracer_lock must be locked
 */
static void trace_bts_cpu(void *arg)
{
	struct trace_array *tr = (struct trace_array *) arg;
	const struct bts_trace *trace;
	unsigned char *at;

	if (unlikely(!tr))
		return;

	if (unlikely(atomic_read(&tr->data[raw_smp_processor_id()]->disabled)))
		return;

	if (unlikely(!this_tracer))
		return;

	ds_suspend_bts(this_tracer);
	trace = ds_read_bts(this_tracer);
	if (!trace)
		goto out;

	for (at = trace->ds.top; (void *)at < trace->ds.end;
	     at += trace->ds.size)
		trace_bts_at(trace, at);

	for (at = trace->ds.begin; (void *)at < trace->ds.top;
	     at += trace->ds.size)
		trace_bts_at(trace, at);

out:
	ds_resume_bts(this_tracer);
}
static void trace_bts_cpu(void *arg)
{
	struct trace_array *tr = (struct trace_array *) arg;
	const struct bts_trace *trace;
	unsigned char *at;

	if (!this_tracer)
		return;

	ds_suspend_bts(this_tracer);
	trace = ds_read_bts(this_tracer);
	if (!trace)
		goto out;

	for (at = trace->ds.top; (void *)at < trace->ds.end;
	     at += trace->ds.size)
		trace_bts_at(tr, trace, at);

	for (at = trace->ds.begin; (void *)at < trace->ds.top;
	     at += trace->ds.size)
		trace_bts_at(tr, trace, at);

out:
	ds_resume_bts(this_tracer);
}
Exemple #3
0
static void ds_selftest_bts_cpu(void *arg)
{
	struct ds_selftest_bts_conf *conf = arg;
	const struct bts_trace *trace;
	void *top;

	if (IS_ERR(conf->tracer)) {
		conf->error = PTR_ERR(conf->tracer);
		conf->tracer = NULL;

		printk(KERN_CONT
		       "initialization failed (err: %d)...", conf->error);
		return;
	}

	/* We should meanwhile have enough trace. */
	conf->error = conf->suspend(conf->tracer);
	if (conf->error < 0)
		return;

	/* Let's see if we can access the trace. */
	trace = ds_read_bts(conf->tracer);

	conf->error = ds_selftest_bts_consistency(trace);
	if (conf->error < 0)
		return;

	/* If everything went well, we should have a few trace entries. */
	if (trace->ds.top == trace->ds.begin) {
		/*
		 * It is possible but highly unlikely that we got a
		 * buffer overflow and end up at exactly the same
		 * position we started from.
		 * Let's issue a warning, but continue.
		 */
		printk(KERN_CONT "no trace/overflow...");
	}

	/* Let's try to read the trace we collected. */
	conf->error =
		ds_selftest_bts_read(conf->tracer, trace,
				     trace->ds.begin, trace->ds.top);
	if (conf->error < 0)
		return;

	/*
	 * Let's read the trace again.
	 * Since we suspended tracing, we should get the same result.
	 */
	top = trace->ds.top;

	trace = ds_read_bts(conf->tracer);
	conf->error = ds_selftest_bts_consistency(trace);
	if (conf->error < 0)
		return;

	if (top != trace->ds.top) {
		printk(KERN_CONT "suspend not working...");
		conf->error = -1;
		return;
	}

	/* Let's collect some more trace - see if resume is working. */
	conf->error = conf->resume(conf->tracer);
	if (conf->error < 0)
		return;

	conf->error = conf->suspend(conf->tracer);
	if (conf->error < 0)
		return;

	trace = ds_read_bts(conf->tracer);

	conf->error = ds_selftest_bts_consistency(trace);
	if (conf->error < 0)
		return;

	if (trace->ds.top == top) {
		/*
		 * It is possible but highly unlikely that we got a
		 * buffer overflow and end up at exactly the same
		 * position we started from.
		 * Let's issue a warning and check the full trace.
		 */
		printk(KERN_CONT
		       "no resume progress/overflow...");

		conf->error =
			ds_selftest_bts_read(conf->tracer, trace,
					     trace->ds.begin, trace->ds.end);
	} else if (trace->ds.top < top) {
		/*
		 * We had a buffer overflow - the entire buffer should
		 * contain trace records.
		 */
		conf->error =
			ds_selftest_bts_read(conf->tracer, trace,
					     trace->ds.begin, trace->ds.end);
	} else {
		/*
		 * It is quite likely that the buffer did not overflow.
		 * Let's just check the delta trace.
		 */
		conf->error =
			ds_selftest_bts_read(conf->tracer, trace, top,
					     trace->ds.top);
	}
	if (conf->error < 0)
		return;

	conf->error = 0;
}