python.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. #include <Python.h>
  2. #include <structmember.h>
  3. #include <inttypes.h>
  4. #include <poll.h>
  5. #include "evlist.h"
  6. #include "evsel.h"
  7. #include "event.h"
  8. #include "cpumap.h"
  9. #include "thread_map.h"
  10. /*
  11. * Support debug printing even though util/debug.c is not linked. That means
  12. * implementing 'verbose' and 'eprintf'.
  13. */
  14. int verbose;
  15. int eprintf(int level, int var, const char *fmt, ...)
  16. {
  17. va_list args;
  18. int ret = 0;
  19. if (var >= level) {
  20. va_start(args, fmt);
  21. ret = vfprintf(stderr, fmt, args);
  22. va_end(args);
  23. }
  24. return ret;
  25. }
  26. /* Define PyVarObject_HEAD_INIT for python 2.5 */
  27. #ifndef PyVarObject_HEAD_INIT
  28. # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
  29. #endif
  30. PyMODINIT_FUNC initperf(void);
  31. #define member_def(type, member, ptype, help) \
  32. { #member, ptype, \
  33. offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
  34. 0, help }
  35. #define sample_member_def(name, member, ptype, help) \
  36. { #name, ptype, \
  37. offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
  38. 0, help }
  39. struct pyrf_event {
  40. PyObject_HEAD
  41. struct perf_sample sample;
  42. union perf_event event;
  43. };
  44. #define sample_members \
  45. sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \
  46. sample_member_def(sample_pid, pid, T_INT, "event pid"), \
  47. sample_member_def(sample_tid, tid, T_INT, "event tid"), \
  48. sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \
  49. sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \
  50. sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \
  51. sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
  52. sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \
  53. sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
  54. static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
  55. static PyMemberDef pyrf_mmap_event__members[] = {
  56. sample_members
  57. member_def(perf_event_header, type, T_UINT, "event type"),
  58. member_def(perf_event_header, misc, T_UINT, "event misc"),
  59. member_def(mmap_event, pid, T_UINT, "event pid"),
  60. member_def(mmap_event, tid, T_UINT, "event tid"),
  61. member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
  62. member_def(mmap_event, len, T_ULONGLONG, "map length"),
  63. member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
  64. member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
  65. { .name = NULL, },
  66. };
  67. static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
  68. {
  69. PyObject *ret;
  70. char *s;
  71. if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
  72. "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
  73. "filename: %s }",
  74. pevent->event.mmap.pid, pevent->event.mmap.tid,
  75. pevent->event.mmap.start, pevent->event.mmap.len,
  76. pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
  77. ret = PyErr_NoMemory();
  78. } else {
  79. ret = PyString_FromString(s);
  80. free(s);
  81. }
  82. return ret;
  83. }
  84. static PyTypeObject pyrf_mmap_event__type = {
  85. PyVarObject_HEAD_INIT(NULL, 0)
  86. .tp_name = "perf.mmap_event",
  87. .tp_basicsize = sizeof(struct pyrf_event),
  88. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  89. .tp_doc = pyrf_mmap_event__doc,
  90. .tp_members = pyrf_mmap_event__members,
  91. .tp_repr = (reprfunc)pyrf_mmap_event__repr,
  92. };
  93. static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
  94. static PyMemberDef pyrf_task_event__members[] = {
  95. sample_members
  96. member_def(perf_event_header, type, T_UINT, "event type"),
  97. member_def(fork_event, pid, T_UINT, "event pid"),
  98. member_def(fork_event, ppid, T_UINT, "event ppid"),
  99. member_def(fork_event, tid, T_UINT, "event tid"),
  100. member_def(fork_event, ptid, T_UINT, "event ptid"),
  101. member_def(fork_event, time, T_ULONGLONG, "timestamp"),
  102. { .name = NULL, },
  103. };
  104. static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
  105. {
  106. return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
  107. "ptid: %u, time: %" PRIu64 "}",
  108. pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
  109. pevent->event.fork.pid,
  110. pevent->event.fork.ppid,
  111. pevent->event.fork.tid,
  112. pevent->event.fork.ptid,
  113. pevent->event.fork.time);
  114. }
  115. static PyTypeObject pyrf_task_event__type = {
  116. PyVarObject_HEAD_INIT(NULL, 0)
  117. .tp_name = "perf.task_event",
  118. .tp_basicsize = sizeof(struct pyrf_event),
  119. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  120. .tp_doc = pyrf_task_event__doc,
  121. .tp_members = pyrf_task_event__members,
  122. .tp_repr = (reprfunc)pyrf_task_event__repr,
  123. };
  124. static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
  125. static PyMemberDef pyrf_comm_event__members[] = {
  126. sample_members
  127. member_def(perf_event_header, type, T_UINT, "event type"),
  128. member_def(comm_event, pid, T_UINT, "event pid"),
  129. member_def(comm_event, tid, T_UINT, "event tid"),
  130. member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
  131. { .name = NULL, },
  132. };
  133. static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
  134. {
  135. return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
  136. pevent->event.comm.pid,
  137. pevent->event.comm.tid,
  138. pevent->event.comm.comm);
  139. }
  140. static PyTypeObject pyrf_comm_event__type = {
  141. PyVarObject_HEAD_INIT(NULL, 0)
  142. .tp_name = "perf.comm_event",
  143. .tp_basicsize = sizeof(struct pyrf_event),
  144. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  145. .tp_doc = pyrf_comm_event__doc,
  146. .tp_members = pyrf_comm_event__members,
  147. .tp_repr = (reprfunc)pyrf_comm_event__repr,
  148. };
  149. static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
  150. static PyMemberDef pyrf_throttle_event__members[] = {
  151. sample_members
  152. member_def(perf_event_header, type, T_UINT, "event type"),
  153. member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
  154. member_def(throttle_event, id, T_ULONGLONG, "event id"),
  155. member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
  156. { .name = NULL, },
  157. };
  158. static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
  159. {
  160. struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
  161. return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
  162. ", stream_id: %" PRIu64 " }",
  163. pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
  164. te->time, te->id, te->stream_id);
  165. }
  166. static PyTypeObject pyrf_throttle_event__type = {
  167. PyVarObject_HEAD_INIT(NULL, 0)
  168. .tp_name = "perf.throttle_event",
  169. .tp_basicsize = sizeof(struct pyrf_event),
  170. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  171. .tp_doc = pyrf_throttle_event__doc,
  172. .tp_members = pyrf_throttle_event__members,
  173. .tp_repr = (reprfunc)pyrf_throttle_event__repr,
  174. };
  175. static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
  176. static PyMemberDef pyrf_lost_event__members[] = {
  177. sample_members
  178. member_def(lost_event, id, T_ULONGLONG, "event id"),
  179. member_def(lost_event, lost, T_ULONGLONG, "number of lost events"),
  180. { .name = NULL, },
  181. };
  182. static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
  183. {
  184. PyObject *ret;
  185. char *s;
  186. if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", "
  187. "lost: %#" PRIx64 " }",
  188. pevent->event.lost.id, pevent->event.lost.lost) < 0) {
  189. ret = PyErr_NoMemory();
  190. } else {
  191. ret = PyString_FromString(s);
  192. free(s);
  193. }
  194. return ret;
  195. }
  196. static PyTypeObject pyrf_lost_event__type = {
  197. PyVarObject_HEAD_INIT(NULL, 0)
  198. .tp_name = "perf.lost_event",
  199. .tp_basicsize = sizeof(struct pyrf_event),
  200. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  201. .tp_doc = pyrf_lost_event__doc,
  202. .tp_members = pyrf_lost_event__members,
  203. .tp_repr = (reprfunc)pyrf_lost_event__repr,
  204. };
  205. static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
  206. static PyMemberDef pyrf_read_event__members[] = {
  207. sample_members
  208. member_def(read_event, pid, T_UINT, "event pid"),
  209. member_def(read_event, tid, T_UINT, "event tid"),
  210. { .name = NULL, },
  211. };
  212. static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
  213. {
  214. return PyString_FromFormat("{ type: read, pid: %u, tid: %u }",
  215. pevent->event.read.pid,
  216. pevent->event.read.tid);
  217. /*
  218. * FIXME: return the array of read values,
  219. * making this method useful ;-)
  220. */
  221. }
  222. static PyTypeObject pyrf_read_event__type = {
  223. PyVarObject_HEAD_INIT(NULL, 0)
  224. .tp_name = "perf.read_event",
  225. .tp_basicsize = sizeof(struct pyrf_event),
  226. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  227. .tp_doc = pyrf_read_event__doc,
  228. .tp_members = pyrf_read_event__members,
  229. .tp_repr = (reprfunc)pyrf_read_event__repr,
  230. };
  231. static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
  232. static PyMemberDef pyrf_sample_event__members[] = {
  233. sample_members
  234. member_def(perf_event_header, type, T_UINT, "event type"),
  235. { .name = NULL, },
  236. };
  237. static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
  238. {
  239. PyObject *ret;
  240. char *s;
  241. if (asprintf(&s, "{ type: sample }") < 0) {
  242. ret = PyErr_NoMemory();
  243. } else {
  244. ret = PyString_FromString(s);
  245. free(s);
  246. }
  247. return ret;
  248. }
  249. static PyTypeObject pyrf_sample_event__type = {
  250. PyVarObject_HEAD_INIT(NULL, 0)
  251. .tp_name = "perf.sample_event",
  252. .tp_basicsize = sizeof(struct pyrf_event),
  253. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  254. .tp_doc = pyrf_sample_event__doc,
  255. .tp_members = pyrf_sample_event__members,
  256. .tp_repr = (reprfunc)pyrf_sample_event__repr,
  257. };
  258. static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object.");
  259. static PyMemberDef pyrf_context_switch_event__members[] = {
  260. sample_members
  261. member_def(perf_event_header, type, T_UINT, "event type"),
  262. member_def(context_switch_event, next_prev_pid, T_UINT, "next/prev pid"),
  263. member_def(context_switch_event, next_prev_tid, T_UINT, "next/prev tid"),
  264. { .name = NULL, },
  265. };
  266. static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent)
  267. {
  268. PyObject *ret;
  269. char *s;
  270. if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
  271. pevent->event.context_switch.next_prev_pid,
  272. pevent->event.context_switch.next_prev_tid,
  273. !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
  274. ret = PyErr_NoMemory();
  275. } else {
  276. ret = PyString_FromString(s);
  277. free(s);
  278. }
  279. return ret;
  280. }
  281. static PyTypeObject pyrf_context_switch_event__type = {
  282. PyVarObject_HEAD_INIT(NULL, 0)
  283. .tp_name = "perf.context_switch_event",
  284. .tp_basicsize = sizeof(struct pyrf_event),
  285. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  286. .tp_doc = pyrf_context_switch_event__doc,
  287. .tp_members = pyrf_context_switch_event__members,
  288. .tp_repr = (reprfunc)pyrf_context_switch_event__repr,
  289. };
  290. static int pyrf_event__setup_types(void)
  291. {
  292. int err;
  293. pyrf_mmap_event__type.tp_new =
  294. pyrf_task_event__type.tp_new =
  295. pyrf_comm_event__type.tp_new =
  296. pyrf_lost_event__type.tp_new =
  297. pyrf_read_event__type.tp_new =
  298. pyrf_sample_event__type.tp_new =
  299. pyrf_context_switch_event__type.tp_new =
  300. pyrf_throttle_event__type.tp_new = PyType_GenericNew;
  301. err = PyType_Ready(&pyrf_mmap_event__type);
  302. if (err < 0)
  303. goto out;
  304. err = PyType_Ready(&pyrf_lost_event__type);
  305. if (err < 0)
  306. goto out;
  307. err = PyType_Ready(&pyrf_task_event__type);
  308. if (err < 0)
  309. goto out;
  310. err = PyType_Ready(&pyrf_comm_event__type);
  311. if (err < 0)
  312. goto out;
  313. err = PyType_Ready(&pyrf_throttle_event__type);
  314. if (err < 0)
  315. goto out;
  316. err = PyType_Ready(&pyrf_read_event__type);
  317. if (err < 0)
  318. goto out;
  319. err = PyType_Ready(&pyrf_sample_event__type);
  320. if (err < 0)
  321. goto out;
  322. err = PyType_Ready(&pyrf_context_switch_event__type);
  323. if (err < 0)
  324. goto out;
  325. out:
  326. return err;
  327. }
  328. static PyTypeObject *pyrf_event__type[] = {
  329. [PERF_RECORD_MMAP] = &pyrf_mmap_event__type,
  330. [PERF_RECORD_LOST] = &pyrf_lost_event__type,
  331. [PERF_RECORD_COMM] = &pyrf_comm_event__type,
  332. [PERF_RECORD_EXIT] = &pyrf_task_event__type,
  333. [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type,
  334. [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
  335. [PERF_RECORD_FORK] = &pyrf_task_event__type,
  336. [PERF_RECORD_READ] = &pyrf_read_event__type,
  337. [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type,
  338. [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type,
  339. [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type,
  340. };
  341. static PyObject *pyrf_event__new(union perf_event *event)
  342. {
  343. struct pyrf_event *pevent;
  344. PyTypeObject *ptype;
  345. if ((event->header.type < PERF_RECORD_MMAP ||
  346. event->header.type > PERF_RECORD_SAMPLE) &&
  347. !(event->header.type == PERF_RECORD_SWITCH ||
  348. event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
  349. return NULL;
  350. ptype = pyrf_event__type[event->header.type];
  351. pevent = PyObject_New(struct pyrf_event, ptype);
  352. if (pevent != NULL)
  353. memcpy(&pevent->event, event, event->header.size);
  354. return (PyObject *)pevent;
  355. }
  356. struct pyrf_cpu_map {
  357. PyObject_HEAD
  358. struct cpu_map *cpus;
  359. };
  360. static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
  361. PyObject *args, PyObject *kwargs)
  362. {
  363. static char *kwlist[] = { "cpustr", NULL };
  364. char *cpustr = NULL;
  365. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
  366. kwlist, &cpustr))
  367. return -1;
  368. pcpus->cpus = cpu_map__new(cpustr);
  369. if (pcpus->cpus == NULL)
  370. return -1;
  371. return 0;
  372. }
  373. static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
  374. {
  375. cpu_map__put(pcpus->cpus);
  376. pcpus->ob_type->tp_free((PyObject*)pcpus);
  377. }
  378. static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
  379. {
  380. struct pyrf_cpu_map *pcpus = (void *)obj;
  381. return pcpus->cpus->nr;
  382. }
  383. static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
  384. {
  385. struct pyrf_cpu_map *pcpus = (void *)obj;
  386. if (i >= pcpus->cpus->nr)
  387. return NULL;
  388. return Py_BuildValue("i", pcpus->cpus->map[i]);
  389. }
  390. static PySequenceMethods pyrf_cpu_map__sequence_methods = {
  391. .sq_length = pyrf_cpu_map__length,
  392. .sq_item = pyrf_cpu_map__item,
  393. };
  394. static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
  395. static PyTypeObject pyrf_cpu_map__type = {
  396. PyVarObject_HEAD_INIT(NULL, 0)
  397. .tp_name = "perf.cpu_map",
  398. .tp_basicsize = sizeof(struct pyrf_cpu_map),
  399. .tp_dealloc = (destructor)pyrf_cpu_map__delete,
  400. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  401. .tp_doc = pyrf_cpu_map__doc,
  402. .tp_as_sequence = &pyrf_cpu_map__sequence_methods,
  403. .tp_init = (initproc)pyrf_cpu_map__init,
  404. };
  405. static int pyrf_cpu_map__setup_types(void)
  406. {
  407. pyrf_cpu_map__type.tp_new = PyType_GenericNew;
  408. return PyType_Ready(&pyrf_cpu_map__type);
  409. }
  410. struct pyrf_thread_map {
  411. PyObject_HEAD
  412. struct thread_map *threads;
  413. };
  414. static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
  415. PyObject *args, PyObject *kwargs)
  416. {
  417. static char *kwlist[] = { "pid", "tid", "uid", NULL };
  418. int pid = -1, tid = -1, uid = UINT_MAX;
  419. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii",
  420. kwlist, &pid, &tid, &uid))
  421. return -1;
  422. pthreads->threads = thread_map__new(pid, tid, uid);
  423. if (pthreads->threads == NULL)
  424. return -1;
  425. return 0;
  426. }
  427. static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
  428. {
  429. thread_map__put(pthreads->threads);
  430. pthreads->ob_type->tp_free((PyObject*)pthreads);
  431. }
  432. static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
  433. {
  434. struct pyrf_thread_map *pthreads = (void *)obj;
  435. return pthreads->threads->nr;
  436. }
  437. static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
  438. {
  439. struct pyrf_thread_map *pthreads = (void *)obj;
  440. if (i >= pthreads->threads->nr)
  441. return NULL;
  442. return Py_BuildValue("i", pthreads->threads->map[i]);
  443. }
  444. static PySequenceMethods pyrf_thread_map__sequence_methods = {
  445. .sq_length = pyrf_thread_map__length,
  446. .sq_item = pyrf_thread_map__item,
  447. };
  448. static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
  449. static PyTypeObject pyrf_thread_map__type = {
  450. PyVarObject_HEAD_INIT(NULL, 0)
  451. .tp_name = "perf.thread_map",
  452. .tp_basicsize = sizeof(struct pyrf_thread_map),
  453. .tp_dealloc = (destructor)pyrf_thread_map__delete,
  454. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  455. .tp_doc = pyrf_thread_map__doc,
  456. .tp_as_sequence = &pyrf_thread_map__sequence_methods,
  457. .tp_init = (initproc)pyrf_thread_map__init,
  458. };
  459. static int pyrf_thread_map__setup_types(void)
  460. {
  461. pyrf_thread_map__type.tp_new = PyType_GenericNew;
  462. return PyType_Ready(&pyrf_thread_map__type);
  463. }
  464. struct pyrf_evsel {
  465. PyObject_HEAD
  466. struct perf_evsel evsel;
  467. };
  468. static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
  469. PyObject *args, PyObject *kwargs)
  470. {
  471. struct perf_event_attr attr = {
  472. .type = PERF_TYPE_HARDWARE,
  473. .config = PERF_COUNT_HW_CPU_CYCLES,
  474. .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
  475. };
  476. static char *kwlist[] = {
  477. "type",
  478. "config",
  479. "sample_freq",
  480. "sample_period",
  481. "sample_type",
  482. "read_format",
  483. "disabled",
  484. "inherit",
  485. "pinned",
  486. "exclusive",
  487. "exclude_user",
  488. "exclude_kernel",
  489. "exclude_hv",
  490. "exclude_idle",
  491. "mmap",
  492. "context_switch",
  493. "comm",
  494. "freq",
  495. "inherit_stat",
  496. "enable_on_exec",
  497. "task",
  498. "watermark",
  499. "precise_ip",
  500. "mmap_data",
  501. "sample_id_all",
  502. "wakeup_events",
  503. "bp_type",
  504. "bp_addr",
  505. "bp_len",
  506. NULL
  507. };
  508. u64 sample_period = 0;
  509. u32 disabled = 0,
  510. inherit = 0,
  511. pinned = 0,
  512. exclusive = 0,
  513. exclude_user = 0,
  514. exclude_kernel = 0,
  515. exclude_hv = 0,
  516. exclude_idle = 0,
  517. mmap = 0,
  518. context_switch = 0,
  519. comm = 0,
  520. freq = 1,
  521. inherit_stat = 0,
  522. enable_on_exec = 0,
  523. task = 0,
  524. watermark = 0,
  525. precise_ip = 0,
  526. mmap_data = 0,
  527. sample_id_all = 1;
  528. int idx = 0;
  529. if (!PyArg_ParseTupleAndKeywords(args, kwargs,
  530. "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
  531. &attr.type, &attr.config, &attr.sample_freq,
  532. &sample_period, &attr.sample_type,
  533. &attr.read_format, &disabled, &inherit,
  534. &pinned, &exclusive, &exclude_user,
  535. &exclude_kernel, &exclude_hv, &exclude_idle,
  536. &mmap, &context_switch, &comm, &freq, &inherit_stat,
  537. &enable_on_exec, &task, &watermark,
  538. &precise_ip, &mmap_data, &sample_id_all,
  539. &attr.wakeup_events, &attr.bp_type,
  540. &attr.bp_addr, &attr.bp_len, &idx))
  541. return -1;
  542. /* union... */
  543. if (sample_period != 0) {
  544. if (attr.sample_freq != 0)
  545. return -1; /* FIXME: throw right exception */
  546. attr.sample_period = sample_period;
  547. }
  548. /* Bitfields */
  549. attr.disabled = disabled;
  550. attr.inherit = inherit;
  551. attr.pinned = pinned;
  552. attr.exclusive = exclusive;
  553. attr.exclude_user = exclude_user;
  554. attr.exclude_kernel = exclude_kernel;
  555. attr.exclude_hv = exclude_hv;
  556. attr.exclude_idle = exclude_idle;
  557. attr.mmap = mmap;
  558. attr.context_switch = context_switch;
  559. attr.comm = comm;
  560. attr.freq = freq;
  561. attr.inherit_stat = inherit_stat;
  562. attr.enable_on_exec = enable_on_exec;
  563. attr.task = task;
  564. attr.watermark = watermark;
  565. attr.precise_ip = precise_ip;
  566. attr.mmap_data = mmap_data;
  567. attr.sample_id_all = sample_id_all;
  568. perf_evsel__init(&pevsel->evsel, &attr, idx);
  569. return 0;
  570. }
  571. static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
  572. {
  573. perf_evsel__exit(&pevsel->evsel);
  574. pevsel->ob_type->tp_free((PyObject*)pevsel);
  575. }
  576. static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
  577. PyObject *args, PyObject *kwargs)
  578. {
  579. struct perf_evsel *evsel = &pevsel->evsel;
  580. struct cpu_map *cpus = NULL;
  581. struct thread_map *threads = NULL;
  582. PyObject *pcpus = NULL, *pthreads = NULL;
  583. int group = 0, inherit = 0;
  584. static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
  585. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
  586. &pcpus, &pthreads, &group, &inherit))
  587. return NULL;
  588. if (pthreads != NULL)
  589. threads = ((struct pyrf_thread_map *)pthreads)->threads;
  590. if (pcpus != NULL)
  591. cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
  592. evsel->attr.inherit = inherit;
  593. /*
  594. * This will group just the fds for this single evsel, to group
  595. * multiple events, use evlist.open().
  596. */
  597. if (perf_evsel__open(evsel, cpus, threads) < 0) {
  598. PyErr_SetFromErrno(PyExc_OSError);
  599. return NULL;
  600. }
  601. Py_INCREF(Py_None);
  602. return Py_None;
  603. }
  604. static PyMethodDef pyrf_evsel__methods[] = {
  605. {
  606. .ml_name = "open",
  607. .ml_meth = (PyCFunction)pyrf_evsel__open,
  608. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  609. .ml_doc = PyDoc_STR("open the event selector file descriptor table.")
  610. },
  611. { .ml_name = NULL, }
  612. };
  613. static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
  614. static PyTypeObject pyrf_evsel__type = {
  615. PyVarObject_HEAD_INIT(NULL, 0)
  616. .tp_name = "perf.evsel",
  617. .tp_basicsize = sizeof(struct pyrf_evsel),
  618. .tp_dealloc = (destructor)pyrf_evsel__delete,
  619. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  620. .tp_doc = pyrf_evsel__doc,
  621. .tp_methods = pyrf_evsel__methods,
  622. .tp_init = (initproc)pyrf_evsel__init,
  623. };
  624. static int pyrf_evsel__setup_types(void)
  625. {
  626. pyrf_evsel__type.tp_new = PyType_GenericNew;
  627. return PyType_Ready(&pyrf_evsel__type);
  628. }
  629. struct pyrf_evlist {
  630. PyObject_HEAD
  631. struct perf_evlist evlist;
  632. };
  633. static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
  634. PyObject *args, PyObject *kwargs __maybe_unused)
  635. {
  636. PyObject *pcpus = NULL, *pthreads = NULL;
  637. struct cpu_map *cpus;
  638. struct thread_map *threads;
  639. if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
  640. return -1;
  641. threads = ((struct pyrf_thread_map *)pthreads)->threads;
  642. cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
  643. perf_evlist__init(&pevlist->evlist, cpus, threads);
  644. return 0;
  645. }
  646. static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
  647. {
  648. perf_evlist__exit(&pevlist->evlist);
  649. pevlist->ob_type->tp_free((PyObject*)pevlist);
  650. }
  651. static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
  652. PyObject *args, PyObject *kwargs)
  653. {
  654. struct perf_evlist *evlist = &pevlist->evlist;
  655. static char *kwlist[] = { "pages", "overwrite", NULL };
  656. int pages = 128, overwrite = false;
  657. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
  658. &pages, &overwrite))
  659. return NULL;
  660. if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
  661. PyErr_SetFromErrno(PyExc_OSError);
  662. return NULL;
  663. }
  664. Py_INCREF(Py_None);
  665. return Py_None;
  666. }
  667. static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
  668. PyObject *args, PyObject *kwargs)
  669. {
  670. struct perf_evlist *evlist = &pevlist->evlist;
  671. static char *kwlist[] = { "timeout", NULL };
  672. int timeout = -1, n;
  673. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
  674. return NULL;
  675. n = perf_evlist__poll(evlist, timeout);
  676. if (n < 0) {
  677. PyErr_SetFromErrno(PyExc_OSError);
  678. return NULL;
  679. }
  680. return Py_BuildValue("i", n);
  681. }
  682. static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
  683. PyObject *args __maybe_unused,
  684. PyObject *kwargs __maybe_unused)
  685. {
  686. struct perf_evlist *evlist = &pevlist->evlist;
  687. PyObject *list = PyList_New(0);
  688. int i;
  689. for (i = 0; i < evlist->pollfd.nr; ++i) {
  690. PyObject *file;
  691. FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
  692. if (fp == NULL)
  693. goto free_list;
  694. file = PyFile_FromFile(fp, "perf", "r", NULL);
  695. if (file == NULL)
  696. goto free_list;
  697. if (PyList_Append(list, file) != 0) {
  698. Py_DECREF(file);
  699. goto free_list;
  700. }
  701. Py_DECREF(file);
  702. }
  703. return list;
  704. free_list:
  705. return PyErr_NoMemory();
  706. }
  707. static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
  708. PyObject *args,
  709. PyObject *kwargs __maybe_unused)
  710. {
  711. struct perf_evlist *evlist = &pevlist->evlist;
  712. PyObject *pevsel;
  713. struct perf_evsel *evsel;
  714. if (!PyArg_ParseTuple(args, "O", &pevsel))
  715. return NULL;
  716. Py_INCREF(pevsel);
  717. evsel = &((struct pyrf_evsel *)pevsel)->evsel;
  718. evsel->idx = evlist->nr_entries;
  719. perf_evlist__add(evlist, evsel);
  720. return Py_BuildValue("i", evlist->nr_entries);
  721. }
  722. static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
  723. PyObject *args, PyObject *kwargs)
  724. {
  725. struct perf_evlist *evlist = &pevlist->evlist;
  726. union perf_event *event;
  727. int sample_id_all = 1, cpu;
  728. static char *kwlist[] = { "cpu", "sample_id_all", NULL };
  729. int err;
  730. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
  731. &cpu, &sample_id_all))
  732. return NULL;
  733. event = perf_evlist__mmap_read(evlist, cpu);
  734. if (event != NULL) {
  735. PyObject *pyevent = pyrf_event__new(event);
  736. struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
  737. perf_evlist__mmap_consume(evlist, cpu);
  738. if (pyevent == NULL)
  739. return PyErr_NoMemory();
  740. err = perf_evlist__parse_sample(evlist, event, &pevent->sample);
  741. if (err)
  742. return PyErr_Format(PyExc_OSError,
  743. "perf: can't parse sample, err=%d", err);
  744. return pyevent;
  745. }
  746. Py_INCREF(Py_None);
  747. return Py_None;
  748. }
  749. static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
  750. PyObject *args, PyObject *kwargs)
  751. {
  752. struct perf_evlist *evlist = &pevlist->evlist;
  753. int group = 0;
  754. static char *kwlist[] = { "group", NULL };
  755. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
  756. return NULL;
  757. if (group)
  758. perf_evlist__set_leader(evlist);
  759. if (perf_evlist__open(evlist) < 0) {
  760. PyErr_SetFromErrno(PyExc_OSError);
  761. return NULL;
  762. }
  763. Py_INCREF(Py_None);
  764. return Py_None;
  765. }
  766. static PyMethodDef pyrf_evlist__methods[] = {
  767. {
  768. .ml_name = "mmap",
  769. .ml_meth = (PyCFunction)pyrf_evlist__mmap,
  770. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  771. .ml_doc = PyDoc_STR("mmap the file descriptor table.")
  772. },
  773. {
  774. .ml_name = "open",
  775. .ml_meth = (PyCFunction)pyrf_evlist__open,
  776. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  777. .ml_doc = PyDoc_STR("open the file descriptors.")
  778. },
  779. {
  780. .ml_name = "poll",
  781. .ml_meth = (PyCFunction)pyrf_evlist__poll,
  782. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  783. .ml_doc = PyDoc_STR("poll the file descriptor table.")
  784. },
  785. {
  786. .ml_name = "get_pollfd",
  787. .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd,
  788. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  789. .ml_doc = PyDoc_STR("get the poll file descriptor table.")
  790. },
  791. {
  792. .ml_name = "add",
  793. .ml_meth = (PyCFunction)pyrf_evlist__add,
  794. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  795. .ml_doc = PyDoc_STR("adds an event selector to the list.")
  796. },
  797. {
  798. .ml_name = "read_on_cpu",
  799. .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu,
  800. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  801. .ml_doc = PyDoc_STR("reads an event.")
  802. },
  803. { .ml_name = NULL, }
  804. };
  805. static Py_ssize_t pyrf_evlist__length(PyObject *obj)
  806. {
  807. struct pyrf_evlist *pevlist = (void *)obj;
  808. return pevlist->evlist.nr_entries;
  809. }
  810. static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
  811. {
  812. struct pyrf_evlist *pevlist = (void *)obj;
  813. struct perf_evsel *pos;
  814. if (i >= pevlist->evlist.nr_entries)
  815. return NULL;
  816. evlist__for_each(&pevlist->evlist, pos) {
  817. if (i-- == 0)
  818. break;
  819. }
  820. return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
  821. }
  822. static PySequenceMethods pyrf_evlist__sequence_methods = {
  823. .sq_length = pyrf_evlist__length,
  824. .sq_item = pyrf_evlist__item,
  825. };
  826. static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
  827. static PyTypeObject pyrf_evlist__type = {
  828. PyVarObject_HEAD_INIT(NULL, 0)
  829. .tp_name = "perf.evlist",
  830. .tp_basicsize = sizeof(struct pyrf_evlist),
  831. .tp_dealloc = (destructor)pyrf_evlist__delete,
  832. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  833. .tp_as_sequence = &pyrf_evlist__sequence_methods,
  834. .tp_doc = pyrf_evlist__doc,
  835. .tp_methods = pyrf_evlist__methods,
  836. .tp_init = (initproc)pyrf_evlist__init,
  837. };
  838. static int pyrf_evlist__setup_types(void)
  839. {
  840. pyrf_evlist__type.tp_new = PyType_GenericNew;
  841. return PyType_Ready(&pyrf_evlist__type);
  842. }
  843. #define PERF_CONST(name) { #name, PERF_##name }
  844. static struct {
  845. const char *name;
  846. int value;
  847. } perf__constants[] = {
  848. PERF_CONST(TYPE_HARDWARE),
  849. PERF_CONST(TYPE_SOFTWARE),
  850. PERF_CONST(TYPE_TRACEPOINT),
  851. PERF_CONST(TYPE_HW_CACHE),
  852. PERF_CONST(TYPE_RAW),
  853. PERF_CONST(TYPE_BREAKPOINT),
  854. PERF_CONST(COUNT_HW_CPU_CYCLES),
  855. PERF_CONST(COUNT_HW_INSTRUCTIONS),
  856. PERF_CONST(COUNT_HW_CACHE_REFERENCES),
  857. PERF_CONST(COUNT_HW_CACHE_MISSES),
  858. PERF_CONST(COUNT_HW_BRANCH_INSTRUCTIONS),
  859. PERF_CONST(COUNT_HW_BRANCH_MISSES),
  860. PERF_CONST(COUNT_HW_BUS_CYCLES),
  861. PERF_CONST(COUNT_HW_CACHE_L1D),
  862. PERF_CONST(COUNT_HW_CACHE_L1I),
  863. PERF_CONST(COUNT_HW_CACHE_LL),
  864. PERF_CONST(COUNT_HW_CACHE_DTLB),
  865. PERF_CONST(COUNT_HW_CACHE_ITLB),
  866. PERF_CONST(COUNT_HW_CACHE_BPU),
  867. PERF_CONST(COUNT_HW_CACHE_OP_READ),
  868. PERF_CONST(COUNT_HW_CACHE_OP_WRITE),
  869. PERF_CONST(COUNT_HW_CACHE_OP_PREFETCH),
  870. PERF_CONST(COUNT_HW_CACHE_RESULT_ACCESS),
  871. PERF_CONST(COUNT_HW_CACHE_RESULT_MISS),
  872. PERF_CONST(COUNT_HW_STALLED_CYCLES_FRONTEND),
  873. PERF_CONST(COUNT_HW_STALLED_CYCLES_BACKEND),
  874. PERF_CONST(COUNT_SW_CPU_CLOCK),
  875. PERF_CONST(COUNT_SW_TASK_CLOCK),
  876. PERF_CONST(COUNT_SW_PAGE_FAULTS),
  877. PERF_CONST(COUNT_SW_CONTEXT_SWITCHES),
  878. PERF_CONST(COUNT_SW_CPU_MIGRATIONS),
  879. PERF_CONST(COUNT_SW_PAGE_FAULTS_MIN),
  880. PERF_CONST(COUNT_SW_PAGE_FAULTS_MAJ),
  881. PERF_CONST(COUNT_SW_ALIGNMENT_FAULTS),
  882. PERF_CONST(COUNT_SW_EMULATION_FAULTS),
  883. PERF_CONST(COUNT_SW_DUMMY),
  884. PERF_CONST(SAMPLE_IP),
  885. PERF_CONST(SAMPLE_TID),
  886. PERF_CONST(SAMPLE_TIME),
  887. PERF_CONST(SAMPLE_ADDR),
  888. PERF_CONST(SAMPLE_READ),
  889. PERF_CONST(SAMPLE_CALLCHAIN),
  890. PERF_CONST(SAMPLE_ID),
  891. PERF_CONST(SAMPLE_CPU),
  892. PERF_CONST(SAMPLE_PERIOD),
  893. PERF_CONST(SAMPLE_STREAM_ID),
  894. PERF_CONST(SAMPLE_RAW),
  895. PERF_CONST(FORMAT_TOTAL_TIME_ENABLED),
  896. PERF_CONST(FORMAT_TOTAL_TIME_RUNNING),
  897. PERF_CONST(FORMAT_ID),
  898. PERF_CONST(FORMAT_GROUP),
  899. PERF_CONST(RECORD_MMAP),
  900. PERF_CONST(RECORD_LOST),
  901. PERF_CONST(RECORD_COMM),
  902. PERF_CONST(RECORD_EXIT),
  903. PERF_CONST(RECORD_THROTTLE),
  904. PERF_CONST(RECORD_UNTHROTTLE),
  905. PERF_CONST(RECORD_FORK),
  906. PERF_CONST(RECORD_READ),
  907. PERF_CONST(RECORD_SAMPLE),
  908. PERF_CONST(RECORD_MMAP2),
  909. PERF_CONST(RECORD_AUX),
  910. PERF_CONST(RECORD_ITRACE_START),
  911. PERF_CONST(RECORD_LOST_SAMPLES),
  912. PERF_CONST(RECORD_SWITCH),
  913. PERF_CONST(RECORD_SWITCH_CPU_WIDE),
  914. PERF_CONST(RECORD_MISC_SWITCH_OUT),
  915. { .name = NULL, },
  916. };
  917. static PyMethodDef perf__methods[] = {
  918. { .ml_name = NULL, }
  919. };
  920. PyMODINIT_FUNC initperf(void)
  921. {
  922. PyObject *obj;
  923. int i;
  924. PyObject *dict, *module = Py_InitModule("perf", perf__methods);
  925. if (module == NULL ||
  926. pyrf_event__setup_types() < 0 ||
  927. pyrf_evlist__setup_types() < 0 ||
  928. pyrf_evsel__setup_types() < 0 ||
  929. pyrf_thread_map__setup_types() < 0 ||
  930. pyrf_cpu_map__setup_types() < 0)
  931. return;
  932. /* The page_size is placed in util object. */
  933. page_size = sysconf(_SC_PAGE_SIZE);
  934. Py_INCREF(&pyrf_evlist__type);
  935. PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
  936. Py_INCREF(&pyrf_evsel__type);
  937. PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
  938. Py_INCREF(&pyrf_thread_map__type);
  939. PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
  940. Py_INCREF(&pyrf_cpu_map__type);
  941. PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
  942. dict = PyModule_GetDict(module);
  943. if (dict == NULL)
  944. goto error;
  945. for (i = 0; perf__constants[i].name != NULL; i++) {
  946. obj = PyInt_FromLong(perf__constants[i].value);
  947. if (obj == NULL)
  948. goto error;
  949. PyDict_SetItemString(dict, perf__constants[i].name, obj);
  950. Py_DECREF(obj);
  951. }
  952. error:
  953. if (PyErr_Occurred())
  954. PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
  955. }
  956. /*
  957. * Dummy, to avoid dragging all the test_attr infrastructure in the python
  958. * binding.
  959. */
  960. void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
  961. int fd, int group_fd, unsigned long flags)
  962. {
  963. }