Re: [PATCH] trace-cruncher: Add API to set tracing CPU affinity

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 10 Jan 2022 15:32:16 +0200
Yordan Karadzhov <y.karadz@xxxxxxxxx> wrote:

> Hi Steven
> 
> On 18.12.21 г. 1:26 ч., Steven Rostedt wrote:
> > From: "Steven Rostedt (VMware)" <rostedt@xxxxxxxxxxx>
> > 
> > Add a set_affinity API that can let the user set what CPUs to enable
> > tracing on.  
> 
> For the sake of completeness we will need APIs to 'clear' and 'get' the CPU affinity as well.

For "clear" you mean to avoid a CPU(s), not clear the mask, right?

> 
> > 
> > Signed-off-by: Steven Rostedt (VMware) <rostedt@xxxxxxxxxxx>
> > ---
> > This depends on the new libtracefs API found here:
> > 
> >    https://patchwork.kernel.org/project/linux-trace-devel/patch/20211217180450.12d3524b@xxxxxxxxxxxxxxxxxx/
> > 
> > This can be worked out later if you have comments. And I'll keep
> > the VMWare tag, as I did write while still working at VMware. I figured
> > that my last patch as a VMware employee would be my first patch
> > to trace-cruncher ;-)  
> 
> This is really symbolic and means a lot for me!

I thought you may appreciate it ;-)

> 
> > 
> >   examples/test-affinity.py |  5 ++++
> >   src/ftracepy-utils.c      | 58 +++++++++++++++++++++++++++++++++++++++
> >   src/ftracepy-utils.h      |  3 ++
> >   src/ftracepy.c            |  5 ++++
> >   4 files changed, 71 insertions(+)
> >   create mode 100755 examples/test-affinity.py
> > 
> > diff --git a/examples/test-affinity.py b/examples/test-affinity.py
> > new file mode 100755
> > index 0000000..1619931
> > --- /dev/null
> > +++ b/examples/test-affinity.py
> > @@ -0,0 +1,5 @@
> > +#!/usr/bin/env python3
> > +
> > +import tracecruncher.ftracepy as ft
> > +
> > +ft.set_affinity(cpus=["0-1","3"]);
> > diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
> > index a735d88..ab39cf1 100644
> > --- a/src/ftracepy-utils.c
> > +++ b/src/ftracepy-utils.c
> > @@ -2394,6 +2394,64 @@ PyObject *PyFtrace_hist(PyObject *self, PyObject *args,
> >   	return NULL;
> >   }
> >   
> > +PyObject *PyFtrace_set_affinity(PyObject *self, PyObject *args,
> > +						PyObject *kwargs)
> > +{
> > +	struct tracefs_instance *instance;
> > +	static char *kwlist[] = {"cpus", "instance", NULL};
> > +	PyObject *py_cpus;
> > +	PyObject *py_inst = NULL;
> > +	const char *cpu_str;
> > +	struct trace_seq seq;
> > +	int ret;
> > +
> > +	if (!PyArg_ParseTupleAndKeywords(args,
> > +					 kwargs,
> > +					 "O|O",
> > +					 kwlist,
> > +					 &py_cpus,
> > +					 &py_inst)) {
> > +		return NULL;
> > +	}
> > +
> > +	trace_seq_init(&seq);  
> 
> There is a global trace_seq object that can be used here. Also you have to check for error.
> Perhaps having:


Don't we need mutex protection if we use a global object?



> 
> 	if (!init_print_seq())
> 		return NULL;

Sure. I left it out as trace_seq has an internal state that won't (at least
it should not) allow anything to be added if it didn't allocate or
something else failed. Thus, you could do all the work and just test at the
end.

> 
> > +
> > +	if (PyUnicode_Check(py_cpus)) {
> > +		cpu_str = (const char *)PyUnicode_DATA(py_cpus);
> > +		if (trace_seq_puts(&seq, cpu_str) < 0)
> > +			goto err_seq;
> > +	} else if (PyList_CheckExact(py_cpus)) {
> > +		int i, n = PyList_Size(py_cpus);
> > +
> > +		for (i = 0; i < n; ++i) {
> > +			cpu_str = str_from_list(py_cpus, i);
> > +			if (i)
> > +				trace_seq_putc(&seq, ',');
> > +			if (trace_seq_puts(&seq, cpu_str) < 0)
> > +				goto err_seq;
> > +		}
> > +	}  
> If py_cpus is neither PyUnicode nor PyList, we have to print error and return NULL.

Yeah, I wasn't sure how much python would detect this. That can be added.

> 
> > +
> > +	if (!get_optional_instance(py_inst, &instance))
> > +		goto err;
> > +
> > +	trace_seq_terminate(&seq);
> > +	ret = tracefs_instance_set_affinity(instance, seq.buffer);
> > +	if (ret < 0) {
> > +		PyErr_SetString(TRACECRUNCHER_ERROR,
> > +				"Invalid \"cpus\" argument.");
> > +		goto err;
> > +	}
> > +
> > +	Py_RETURN_NONE;
> > +err_seq:
> > +	PyErr_SetString(TRACECRUNCHER_ERROR,
> > +			"Internal processing string error.");
> > +err:
> > +	trace_seq_destroy(&seq);
> > +	return NULL;
> > +}
> > +
> >   PyObject *PyFtrace_set_ftrace_loglevel(PyObject *self, PyObject *args,
> >   						       PyObject *kwargs)
> >   {
> > diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
> > index d09c8bf..67f67ab 100644
> > --- a/src/ftracepy-utils.h
> > +++ b/src/ftracepy-utils.h
> > @@ -208,6 +208,9 @@ PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
> >   PyObject *PyFtrace_hist(PyObject *self, PyObject *args,
> >   					PyObject *kwargs);
> >   
> > +PyObject *PyFtrace_set_affinity(PyObject *self, PyObject *args,
> > +						PyObject *kwargs);
> > +
> >   PyObject *PyFtrace_set_ftrace_loglevel(PyObject *self, PyObject *args,
> >   						       PyObject *kwargs);
> >   
> > diff --git a/src/ftracepy.c b/src/ftracepy.c
> > index b270b71..634f357 100644
> > --- a/src/ftracepy.c
> > +++ b/src/ftracepy.c
> > @@ -377,6 +377,11 @@ static PyMethodDef ftracepy_methods[] = {
> >   	 METH_VARARGS | METH_KEYWORDS,
> >   	 "Define a histogram."
> >   	},
> > +	{"set_affinity",
> > +	 (PyCFunction) PyFtrace_set_affinity,
> > +	 METH_VARARGS | METH_KEYWORDS,
> > +	 "Find an existing ftrace instance."  
> A short description of the method has to be provided here.

OK, will do in v2.

Cheers,

-- Steve



[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux