python.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  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. struct throttle_event {
  11. struct perf_event_header header;
  12. u64 time;
  13. u64 id;
  14. u64 stream_id;
  15. };
  16. PyMODINIT_FUNC initperf(void);
  17. #define member_def(type, member, ptype, help) \
  18. { #member, ptype, \
  19. offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
  20. 0, help }
  21. #define sample_member_def(name, member, ptype, help) \
  22. { #name, ptype, \
  23. offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
  24. 0, help }
  25. struct pyrf_event {
  26. PyObject_HEAD
  27. struct perf_sample sample;
  28. union perf_event event;
  29. };
  30. #define sample_members \
  31. sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \
  32. sample_member_def(sample_pid, pid, T_INT, "event pid"), \
  33. sample_member_def(sample_tid, tid, T_INT, "event tid"), \
  34. sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \
  35. sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \
  36. sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \
  37. sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
  38. sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \
  39. sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
  40. static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
  41. static PyMemberDef pyrf_mmap_event__members[] = {
  42. sample_members
  43. member_def(perf_event_header, type, T_UINT, "event type"),
  44. member_def(mmap_event, pid, T_UINT, "event pid"),
  45. member_def(mmap_event, tid, T_UINT, "event tid"),
  46. member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
  47. member_def(mmap_event, len, T_ULONGLONG, "map length"),
  48. member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
  49. member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
  50. { .name = NULL, },
  51. };
  52. static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
  53. {
  54. PyObject *ret;
  55. char *s;
  56. if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
  57. "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
  58. "filename: %s }",
  59. pevent->event.mmap.pid, pevent->event.mmap.tid,
  60. pevent->event.mmap.start, pevent->event.mmap.len,
  61. pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
  62. ret = PyErr_NoMemory();
  63. } else {
  64. ret = PyString_FromString(s);
  65. free(s);
  66. }
  67. return ret;
  68. }
  69. static PyTypeObject pyrf_mmap_event__type = {
  70. PyVarObject_HEAD_INIT(NULL, 0)
  71. .tp_name = "perf.mmap_event",
  72. .tp_basicsize = sizeof(struct pyrf_event),
  73. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  74. .tp_doc = pyrf_mmap_event__doc,
  75. .tp_members = pyrf_mmap_event__members,
  76. .tp_repr = (reprfunc)pyrf_mmap_event__repr,
  77. };
  78. static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
  79. static PyMemberDef pyrf_task_event__members[] = {
  80. sample_members
  81. member_def(perf_event_header, type, T_UINT, "event type"),
  82. member_def(fork_event, pid, T_UINT, "event pid"),
  83. member_def(fork_event, ppid, T_UINT, "event ppid"),
  84. member_def(fork_event, tid, T_UINT, "event tid"),
  85. member_def(fork_event, ptid, T_UINT, "event ptid"),
  86. member_def(fork_event, time, T_ULONGLONG, "timestamp"),
  87. { .name = NULL, },
  88. };
  89. static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
  90. {
  91. return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
  92. "ptid: %u, time: %" PRIu64 "}",
  93. pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
  94. pevent->event.fork.pid,
  95. pevent->event.fork.ppid,
  96. pevent->event.fork.tid,
  97. pevent->event.fork.ptid,
  98. pevent->event.fork.time);
  99. }
  100. static PyTypeObject pyrf_task_event__type = {
  101. PyVarObject_HEAD_INIT(NULL, 0)
  102. .tp_name = "perf.task_event",
  103. .tp_basicsize = sizeof(struct pyrf_event),
  104. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  105. .tp_doc = pyrf_task_event__doc,
  106. .tp_members = pyrf_task_event__members,
  107. .tp_repr = (reprfunc)pyrf_task_event__repr,
  108. };
  109. static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
  110. static PyMemberDef pyrf_comm_event__members[] = {
  111. sample_members
  112. member_def(perf_event_header, type, T_UINT, "event type"),
  113. member_def(comm_event, pid, T_UINT, "event pid"),
  114. member_def(comm_event, tid, T_UINT, "event tid"),
  115. member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
  116. { .name = NULL, },
  117. };
  118. static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
  119. {
  120. return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
  121. pevent->event.comm.pid,
  122. pevent->event.comm.tid,
  123. pevent->event.comm.comm);
  124. }
  125. static PyTypeObject pyrf_comm_event__type = {
  126. PyVarObject_HEAD_INIT(NULL, 0)
  127. .tp_name = "perf.comm_event",
  128. .tp_basicsize = sizeof(struct pyrf_event),
  129. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  130. .tp_doc = pyrf_comm_event__doc,
  131. .tp_members = pyrf_comm_event__members,
  132. .tp_repr = (reprfunc)pyrf_comm_event__repr,
  133. };
  134. static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
  135. static PyMemberDef pyrf_throttle_event__members[] = {
  136. sample_members
  137. member_def(perf_event_header, type, T_UINT, "event type"),
  138. member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
  139. member_def(throttle_event, id, T_ULONGLONG, "event id"),
  140. member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
  141. { .name = NULL, },
  142. };
  143. static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
  144. {
  145. struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
  146. return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
  147. ", stream_id: %" PRIu64 " }",
  148. pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
  149. te->time, te->id, te->stream_id);
  150. }
  151. static PyTypeObject pyrf_throttle_event__type = {
  152. PyVarObject_HEAD_INIT(NULL, 0)
  153. .tp_name = "perf.throttle_event",
  154. .tp_basicsize = sizeof(struct pyrf_event),
  155. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  156. .tp_doc = pyrf_throttle_event__doc,
  157. .tp_members = pyrf_throttle_event__members,
  158. .tp_repr = (reprfunc)pyrf_throttle_event__repr,
  159. };
  160. static int pyrf_event__setup_types(void)
  161. {
  162. int err;
  163. pyrf_mmap_event__type.tp_new =
  164. pyrf_task_event__type.tp_new =
  165. pyrf_comm_event__type.tp_new =
  166. pyrf_throttle_event__type.tp_new = PyType_GenericNew;
  167. err = PyType_Ready(&pyrf_mmap_event__type);
  168. if (err < 0)
  169. goto out;
  170. err = PyType_Ready(&pyrf_task_event__type);
  171. if (err < 0)
  172. goto out;
  173. err = PyType_Ready(&pyrf_comm_event__type);
  174. if (err < 0)
  175. goto out;
  176. err = PyType_Ready(&pyrf_throttle_event__type);
  177. if (err < 0)
  178. goto out;
  179. out:
  180. return err;
  181. }
  182. static PyTypeObject *pyrf_event__type[] = {
  183. [PERF_RECORD_MMAP] = &pyrf_mmap_event__type,
  184. [PERF_RECORD_LOST] = &pyrf_mmap_event__type,
  185. [PERF_RECORD_COMM] = &pyrf_comm_event__type,
  186. [PERF_RECORD_EXIT] = &pyrf_task_event__type,
  187. [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type,
  188. [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
  189. [PERF_RECORD_FORK] = &pyrf_task_event__type,
  190. [PERF_RECORD_READ] = &pyrf_mmap_event__type,
  191. [PERF_RECORD_SAMPLE] = &pyrf_mmap_event__type,
  192. };
  193. static PyObject *pyrf_event__new(union perf_event *event)
  194. {
  195. struct pyrf_event *pevent;
  196. PyTypeObject *ptype;
  197. if (event->header.type < PERF_RECORD_MMAP ||
  198. event->header.type > PERF_RECORD_SAMPLE)
  199. return NULL;
  200. ptype = pyrf_event__type[event->header.type];
  201. pevent = PyObject_New(struct pyrf_event, ptype);
  202. if (pevent != NULL)
  203. memcpy(&pevent->event, event, event->header.size);
  204. return (PyObject *)pevent;
  205. }
  206. struct pyrf_cpu_map {
  207. PyObject_HEAD
  208. struct cpu_map *cpus;
  209. };
  210. static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
  211. PyObject *args, PyObject *kwargs)
  212. {
  213. static char *kwlist[] = { "cpustr", NULL, NULL, };
  214. char *cpustr = NULL;
  215. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
  216. kwlist, &cpustr))
  217. return -1;
  218. pcpus->cpus = cpu_map__new(cpustr);
  219. if (pcpus->cpus == NULL)
  220. return -1;
  221. return 0;
  222. }
  223. static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
  224. {
  225. cpu_map__delete(pcpus->cpus);
  226. pcpus->ob_type->tp_free((PyObject*)pcpus);
  227. }
  228. static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
  229. {
  230. struct pyrf_cpu_map *pcpus = (void *)obj;
  231. return pcpus->cpus->nr;
  232. }
  233. static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
  234. {
  235. struct pyrf_cpu_map *pcpus = (void *)obj;
  236. if (i >= pcpus->cpus->nr)
  237. return NULL;
  238. return Py_BuildValue("i", pcpus->cpus->map[i]);
  239. }
  240. static PySequenceMethods pyrf_cpu_map__sequence_methods = {
  241. .sq_length = pyrf_cpu_map__length,
  242. .sq_item = pyrf_cpu_map__item,
  243. };
  244. static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
  245. static PyTypeObject pyrf_cpu_map__type = {
  246. PyVarObject_HEAD_INIT(NULL, 0)
  247. .tp_name = "perf.cpu_map",
  248. .tp_basicsize = sizeof(struct pyrf_cpu_map),
  249. .tp_dealloc = (destructor)pyrf_cpu_map__delete,
  250. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  251. .tp_doc = pyrf_cpu_map__doc,
  252. .tp_as_sequence = &pyrf_cpu_map__sequence_methods,
  253. .tp_init = (initproc)pyrf_cpu_map__init,
  254. };
  255. static int pyrf_cpu_map__setup_types(void)
  256. {
  257. pyrf_cpu_map__type.tp_new = PyType_GenericNew;
  258. return PyType_Ready(&pyrf_cpu_map__type);
  259. }
  260. struct pyrf_thread_map {
  261. PyObject_HEAD
  262. struct thread_map *threads;
  263. };
  264. static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
  265. PyObject *args, PyObject *kwargs)
  266. {
  267. static char *kwlist[] = { "pid", "tid", NULL, NULL, };
  268. int pid = -1, tid = -1;
  269. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
  270. kwlist, &pid, &tid))
  271. return -1;
  272. pthreads->threads = thread_map__new(pid, tid);
  273. if (pthreads->threads == NULL)
  274. return -1;
  275. return 0;
  276. }
  277. static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
  278. {
  279. thread_map__delete(pthreads->threads);
  280. pthreads->ob_type->tp_free((PyObject*)pthreads);
  281. }
  282. static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
  283. {
  284. struct pyrf_thread_map *pthreads = (void *)obj;
  285. return pthreads->threads->nr;
  286. }
  287. static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
  288. {
  289. struct pyrf_thread_map *pthreads = (void *)obj;
  290. if (i >= pthreads->threads->nr)
  291. return NULL;
  292. return Py_BuildValue("i", pthreads->threads->map[i]);
  293. }
  294. static PySequenceMethods pyrf_thread_map__sequence_methods = {
  295. .sq_length = pyrf_thread_map__length,
  296. .sq_item = pyrf_thread_map__item,
  297. };
  298. static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
  299. static PyTypeObject pyrf_thread_map__type = {
  300. PyVarObject_HEAD_INIT(NULL, 0)
  301. .tp_name = "perf.thread_map",
  302. .tp_basicsize = sizeof(struct pyrf_thread_map),
  303. .tp_dealloc = (destructor)pyrf_thread_map__delete,
  304. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  305. .tp_doc = pyrf_thread_map__doc,
  306. .tp_as_sequence = &pyrf_thread_map__sequence_methods,
  307. .tp_init = (initproc)pyrf_thread_map__init,
  308. };
  309. static int pyrf_thread_map__setup_types(void)
  310. {
  311. pyrf_thread_map__type.tp_new = PyType_GenericNew;
  312. return PyType_Ready(&pyrf_thread_map__type);
  313. }
  314. struct pyrf_evsel {
  315. PyObject_HEAD
  316. struct perf_evsel evsel;
  317. };
  318. static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
  319. PyObject *args, PyObject *kwargs)
  320. {
  321. struct perf_event_attr attr = {
  322. .type = PERF_TYPE_HARDWARE,
  323. .config = PERF_COUNT_HW_CPU_CYCLES,
  324. .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
  325. };
  326. static char *kwlist[] = {
  327. "type",
  328. "config",
  329. "sample_freq",
  330. "sample_period",
  331. "sample_type",
  332. "read_format",
  333. "disabled",
  334. "inherit",
  335. "pinned",
  336. "exclusive",
  337. "exclude_user",
  338. "exclude_kernel",
  339. "exclude_hv",
  340. "exclude_idle",
  341. "mmap",
  342. "comm",
  343. "freq",
  344. "inherit_stat",
  345. "enable_on_exec",
  346. "task",
  347. "watermark",
  348. "precise_ip",
  349. "mmap_data",
  350. "sample_id_all",
  351. "wakeup_events",
  352. "bp_type",
  353. "bp_addr",
  354. "bp_len", NULL, NULL, };
  355. u64 sample_period = 0;
  356. u32 disabled = 0,
  357. inherit = 0,
  358. pinned = 0,
  359. exclusive = 0,
  360. exclude_user = 0,
  361. exclude_kernel = 0,
  362. exclude_hv = 0,
  363. exclude_idle = 0,
  364. mmap = 0,
  365. comm = 0,
  366. freq = 1,
  367. inherit_stat = 0,
  368. enable_on_exec = 0,
  369. task = 0,
  370. watermark = 0,
  371. precise_ip = 0,
  372. mmap_data = 0,
  373. sample_id_all = 1;
  374. int idx = 0;
  375. if (!PyArg_ParseTupleAndKeywords(args, kwargs,
  376. "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
  377. &attr.type, &attr.config, &attr.sample_freq,
  378. &sample_period, &attr.sample_type,
  379. &attr.read_format, &disabled, &inherit,
  380. &pinned, &exclusive, &exclude_user,
  381. &exclude_kernel, &exclude_hv, &exclude_idle,
  382. &mmap, &comm, &freq, &inherit_stat,
  383. &enable_on_exec, &task, &watermark,
  384. &precise_ip, &mmap_data, &sample_id_all,
  385. &attr.wakeup_events, &attr.bp_type,
  386. &attr.bp_addr, &attr.bp_len, &idx))
  387. return -1;
  388. /* union... */
  389. if (sample_period != 0) {
  390. if (attr.sample_freq != 0)
  391. return -1; /* FIXME: throw right exception */
  392. attr.sample_period = sample_period;
  393. }
  394. /* Bitfields */
  395. attr.disabled = disabled;
  396. attr.inherit = inherit;
  397. attr.pinned = pinned;
  398. attr.exclusive = exclusive;
  399. attr.exclude_user = exclude_user;
  400. attr.exclude_kernel = exclude_kernel;
  401. attr.exclude_hv = exclude_hv;
  402. attr.exclude_idle = exclude_idle;
  403. attr.mmap = mmap;
  404. attr.comm = comm;
  405. attr.freq = freq;
  406. attr.inherit_stat = inherit_stat;
  407. attr.enable_on_exec = enable_on_exec;
  408. attr.task = task;
  409. attr.watermark = watermark;
  410. attr.precise_ip = precise_ip;
  411. attr.mmap_data = mmap_data;
  412. attr.sample_id_all = sample_id_all;
  413. perf_evsel__init(&pevsel->evsel, &attr, idx);
  414. return 0;
  415. }
  416. static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
  417. {
  418. perf_evsel__exit(&pevsel->evsel);
  419. pevsel->ob_type->tp_free((PyObject*)pevsel);
  420. }
  421. static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
  422. PyObject *args, PyObject *kwargs)
  423. {
  424. struct perf_evsel *evsel = &pevsel->evsel;
  425. struct cpu_map *cpus = NULL;
  426. struct thread_map *threads = NULL;
  427. PyObject *pcpus = NULL, *pthreads = NULL;
  428. int group = 0, overwrite = 0;
  429. static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL};
  430. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
  431. &pcpus, &pthreads, &group, &overwrite))
  432. return NULL;
  433. if (pthreads != NULL)
  434. threads = ((struct pyrf_thread_map *)pthreads)->threads;
  435. if (pcpus != NULL)
  436. cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
  437. if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) {
  438. PyErr_SetFromErrno(PyExc_OSError);
  439. return NULL;
  440. }
  441. Py_INCREF(Py_None);
  442. return Py_None;
  443. }
  444. static PyMethodDef pyrf_evsel__methods[] = {
  445. {
  446. .ml_name = "open",
  447. .ml_meth = (PyCFunction)pyrf_evsel__open,
  448. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  449. .ml_doc = PyDoc_STR("open the event selector file descriptor table.")
  450. },
  451. { .ml_name = NULL, }
  452. };
  453. static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
  454. static PyTypeObject pyrf_evsel__type = {
  455. PyVarObject_HEAD_INIT(NULL, 0)
  456. .tp_name = "perf.evsel",
  457. .tp_basicsize = sizeof(struct pyrf_evsel),
  458. .tp_dealloc = (destructor)pyrf_evsel__delete,
  459. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  460. .tp_doc = pyrf_evsel__doc,
  461. .tp_methods = pyrf_evsel__methods,
  462. .tp_init = (initproc)pyrf_evsel__init,
  463. };
  464. static int pyrf_evsel__setup_types(void)
  465. {
  466. pyrf_evsel__type.tp_new = PyType_GenericNew;
  467. return PyType_Ready(&pyrf_evsel__type);
  468. }
  469. struct pyrf_evlist {
  470. PyObject_HEAD
  471. struct perf_evlist evlist;
  472. };
  473. static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
  474. PyObject *args, PyObject *kwargs __used)
  475. {
  476. PyObject *pcpus = NULL, *pthreads = NULL;
  477. struct cpu_map *cpus;
  478. struct thread_map *threads;
  479. if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
  480. return -1;
  481. threads = ((struct pyrf_thread_map *)pthreads)->threads;
  482. cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
  483. perf_evlist__init(&pevlist->evlist, cpus, threads);
  484. return 0;
  485. }
  486. static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
  487. {
  488. perf_evlist__exit(&pevlist->evlist);
  489. pevlist->ob_type->tp_free((PyObject*)pevlist);
  490. }
  491. static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
  492. PyObject *args, PyObject *kwargs)
  493. {
  494. struct perf_evlist *evlist = &pevlist->evlist;
  495. static char *kwlist[] = {"pages", "overwrite",
  496. NULL, NULL};
  497. int pages = 128, overwrite = false;
  498. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
  499. &pages, &overwrite))
  500. return NULL;
  501. if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
  502. PyErr_SetFromErrno(PyExc_OSError);
  503. return NULL;
  504. }
  505. Py_INCREF(Py_None);
  506. return Py_None;
  507. }
  508. static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
  509. PyObject *args, PyObject *kwargs)
  510. {
  511. struct perf_evlist *evlist = &pevlist->evlist;
  512. static char *kwlist[] = {"timeout", NULL, NULL};
  513. int timeout = -1, n;
  514. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
  515. return NULL;
  516. n = poll(evlist->pollfd, evlist->nr_fds, timeout);
  517. if (n < 0) {
  518. PyErr_SetFromErrno(PyExc_OSError);
  519. return NULL;
  520. }
  521. return Py_BuildValue("i", n);
  522. }
  523. static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
  524. PyObject *args __used, PyObject *kwargs __used)
  525. {
  526. struct perf_evlist *evlist = &pevlist->evlist;
  527. PyObject *list = PyList_New(0);
  528. int i;
  529. for (i = 0; i < evlist->nr_fds; ++i) {
  530. PyObject *file;
  531. FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
  532. if (fp == NULL)
  533. goto free_list;
  534. file = PyFile_FromFile(fp, "perf", "r", NULL);
  535. if (file == NULL)
  536. goto free_list;
  537. if (PyList_Append(list, file) != 0) {
  538. Py_DECREF(file);
  539. goto free_list;
  540. }
  541. Py_DECREF(file);
  542. }
  543. return list;
  544. free_list:
  545. return PyErr_NoMemory();
  546. }
  547. static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
  548. PyObject *args, PyObject *kwargs __used)
  549. {
  550. struct perf_evlist *evlist = &pevlist->evlist;
  551. PyObject *pevsel;
  552. struct perf_evsel *evsel;
  553. if (!PyArg_ParseTuple(args, "O", &pevsel))
  554. return NULL;
  555. Py_INCREF(pevsel);
  556. evsel = &((struct pyrf_evsel *)pevsel)->evsel;
  557. evsel->idx = evlist->nr_entries;
  558. perf_evlist__add(evlist, evsel);
  559. return Py_BuildValue("i", evlist->nr_entries);
  560. }
  561. static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
  562. PyObject *args, PyObject *kwargs)
  563. {
  564. struct perf_evlist *evlist = &pevlist->evlist;
  565. union perf_event *event;
  566. int sample_id_all = 1, cpu;
  567. static char *kwlist[] = {"sample_id_all", NULL, NULL};
  568. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
  569. &cpu, &sample_id_all))
  570. return NULL;
  571. event = perf_evlist__read_on_cpu(evlist, cpu);
  572. if (event != NULL) {
  573. struct perf_evsel *first;
  574. PyObject *pyevent = pyrf_event__new(event);
  575. struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
  576. if (pyevent == NULL)
  577. return PyErr_NoMemory();
  578. first = list_entry(evlist->entries.next, struct perf_evsel, node);
  579. perf_event__parse_sample(event, first->attr.sample_type, sample_id_all,
  580. &pevent->sample);
  581. return pyevent;
  582. }
  583. Py_INCREF(Py_None);
  584. return Py_None;
  585. }
  586. static PyMethodDef pyrf_evlist__methods[] = {
  587. {
  588. .ml_name = "mmap",
  589. .ml_meth = (PyCFunction)pyrf_evlist__mmap,
  590. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  591. .ml_doc = PyDoc_STR("mmap the file descriptor table.")
  592. },
  593. {
  594. .ml_name = "poll",
  595. .ml_meth = (PyCFunction)pyrf_evlist__poll,
  596. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  597. .ml_doc = PyDoc_STR("poll the file descriptor table.")
  598. },
  599. {
  600. .ml_name = "get_pollfd",
  601. .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd,
  602. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  603. .ml_doc = PyDoc_STR("get the poll file descriptor table.")
  604. },
  605. {
  606. .ml_name = "add",
  607. .ml_meth = (PyCFunction)pyrf_evlist__add,
  608. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  609. .ml_doc = PyDoc_STR("adds an event selector to the list.")
  610. },
  611. {
  612. .ml_name = "read_on_cpu",
  613. .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu,
  614. .ml_flags = METH_VARARGS | METH_KEYWORDS,
  615. .ml_doc = PyDoc_STR("reads an event.")
  616. },
  617. { .ml_name = NULL, }
  618. };
  619. static Py_ssize_t pyrf_evlist__length(PyObject *obj)
  620. {
  621. struct pyrf_evlist *pevlist = (void *)obj;
  622. return pevlist->evlist.nr_entries;
  623. }
  624. static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
  625. {
  626. struct pyrf_evlist *pevlist = (void *)obj;
  627. struct perf_evsel *pos;
  628. if (i >= pevlist->evlist.nr_entries)
  629. return NULL;
  630. list_for_each_entry(pos, &pevlist->evlist.entries, node)
  631. if (i-- == 0)
  632. break;
  633. return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
  634. }
  635. static PySequenceMethods pyrf_evlist__sequence_methods = {
  636. .sq_length = pyrf_evlist__length,
  637. .sq_item = pyrf_evlist__item,
  638. };
  639. static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
  640. static PyTypeObject pyrf_evlist__type = {
  641. PyVarObject_HEAD_INIT(NULL, 0)
  642. .tp_name = "perf.evlist",
  643. .tp_basicsize = sizeof(struct pyrf_evlist),
  644. .tp_dealloc = (destructor)pyrf_evlist__delete,
  645. .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
  646. .tp_as_sequence = &pyrf_evlist__sequence_methods,
  647. .tp_doc = pyrf_evlist__doc,
  648. .tp_methods = pyrf_evlist__methods,
  649. .tp_init = (initproc)pyrf_evlist__init,
  650. };
  651. static int pyrf_evlist__setup_types(void)
  652. {
  653. pyrf_evlist__type.tp_new = PyType_GenericNew;
  654. return PyType_Ready(&pyrf_evlist__type);
  655. }
  656. static struct {
  657. const char *name;
  658. int value;
  659. } perf__constants[] = {
  660. { "TYPE_HARDWARE", PERF_TYPE_HARDWARE },
  661. { "TYPE_SOFTWARE", PERF_TYPE_SOFTWARE },
  662. { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
  663. { "TYPE_HW_CACHE", PERF_TYPE_HW_CACHE },
  664. { "TYPE_RAW", PERF_TYPE_RAW },
  665. { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
  666. { "COUNT_HW_CPU_CYCLES", PERF_COUNT_HW_CPU_CYCLES },
  667. { "COUNT_HW_INSTRUCTIONS", PERF_COUNT_HW_INSTRUCTIONS },
  668. { "COUNT_HW_CACHE_REFERENCES", PERF_COUNT_HW_CACHE_REFERENCES },
  669. { "COUNT_HW_CACHE_MISSES", PERF_COUNT_HW_CACHE_MISSES },
  670. { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
  671. { "COUNT_HW_BRANCH_MISSES", PERF_COUNT_HW_BRANCH_MISSES },
  672. { "COUNT_HW_BUS_CYCLES", PERF_COUNT_HW_BUS_CYCLES },
  673. { "COUNT_HW_CACHE_L1D", PERF_COUNT_HW_CACHE_L1D },
  674. { "COUNT_HW_CACHE_L1I", PERF_COUNT_HW_CACHE_L1I },
  675. { "COUNT_HW_CACHE_LL", PERF_COUNT_HW_CACHE_LL },
  676. { "COUNT_HW_CACHE_DTLB", PERF_COUNT_HW_CACHE_DTLB },
  677. { "COUNT_HW_CACHE_ITLB", PERF_COUNT_HW_CACHE_ITLB },
  678. { "COUNT_HW_CACHE_BPU", PERF_COUNT_HW_CACHE_BPU },
  679. { "COUNT_HW_CACHE_OP_READ", PERF_COUNT_HW_CACHE_OP_READ },
  680. { "COUNT_HW_CACHE_OP_WRITE", PERF_COUNT_HW_CACHE_OP_WRITE },
  681. { "COUNT_HW_CACHE_OP_PREFETCH", PERF_COUNT_HW_CACHE_OP_PREFETCH },
  682. { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
  683. { "COUNT_HW_CACHE_RESULT_MISS", PERF_COUNT_HW_CACHE_RESULT_MISS },
  684. { "COUNT_SW_CPU_CLOCK", PERF_COUNT_SW_CPU_CLOCK },
  685. { "COUNT_SW_TASK_CLOCK", PERF_COUNT_SW_TASK_CLOCK },
  686. { "COUNT_SW_PAGE_FAULTS", PERF_COUNT_SW_PAGE_FAULTS },
  687. { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
  688. { "COUNT_SW_CPU_MIGRATIONS", PERF_COUNT_SW_CPU_MIGRATIONS },
  689. { "COUNT_SW_PAGE_FAULTS_MIN", PERF_COUNT_SW_PAGE_FAULTS_MIN },
  690. { "COUNT_SW_PAGE_FAULTS_MAJ", PERF_COUNT_SW_PAGE_FAULTS_MAJ },
  691. { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
  692. { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
  693. { "SAMPLE_IP", PERF_SAMPLE_IP },
  694. { "SAMPLE_TID", PERF_SAMPLE_TID },
  695. { "SAMPLE_TIME", PERF_SAMPLE_TIME },
  696. { "SAMPLE_ADDR", PERF_SAMPLE_ADDR },
  697. { "SAMPLE_READ", PERF_SAMPLE_READ },
  698. { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
  699. { "SAMPLE_ID", PERF_SAMPLE_ID },
  700. { "SAMPLE_CPU", PERF_SAMPLE_CPU },
  701. { "SAMPLE_PERIOD", PERF_SAMPLE_PERIOD },
  702. { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
  703. { "SAMPLE_RAW", PERF_SAMPLE_RAW },
  704. { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
  705. { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
  706. { "FORMAT_ID", PERF_FORMAT_ID },
  707. { "FORMAT_GROUP", PERF_FORMAT_GROUP },
  708. { "RECORD_MMAP", PERF_RECORD_MMAP },
  709. { "RECORD_LOST", PERF_RECORD_LOST },
  710. { "RECORD_COMM", PERF_RECORD_COMM },
  711. { "RECORD_EXIT", PERF_RECORD_EXIT },
  712. { "RECORD_THROTTLE", PERF_RECORD_THROTTLE },
  713. { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
  714. { "RECORD_FORK", PERF_RECORD_FORK },
  715. { "RECORD_READ", PERF_RECORD_READ },
  716. { "RECORD_SAMPLE", PERF_RECORD_SAMPLE },
  717. { .name = NULL, },
  718. };
  719. static PyMethodDef perf__methods[] = {
  720. { .ml_name = NULL, }
  721. };
  722. PyMODINIT_FUNC initperf(void)
  723. {
  724. PyObject *obj;
  725. int i;
  726. PyObject *dict, *module = Py_InitModule("perf", perf__methods);
  727. if (module == NULL ||
  728. pyrf_event__setup_types() < 0 ||
  729. pyrf_evlist__setup_types() < 0 ||
  730. pyrf_evsel__setup_types() < 0 ||
  731. pyrf_thread_map__setup_types() < 0 ||
  732. pyrf_cpu_map__setup_types() < 0)
  733. return;
  734. Py_INCREF(&pyrf_evlist__type);
  735. PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
  736. Py_INCREF(&pyrf_evsel__type);
  737. PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
  738. Py_INCREF(&pyrf_thread_map__type);
  739. PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
  740. Py_INCREF(&pyrf_cpu_map__type);
  741. PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
  742. dict = PyModule_GetDict(module);
  743. if (dict == NULL)
  744. goto error;
  745. for (i = 0; perf__constants[i].name != NULL; i++) {
  746. obj = PyInt_FromLong(perf__constants[i].value);
  747. if (obj == NULL)
  748. goto error;
  749. PyDict_SetItemString(dict, perf__constants[i].name, obj);
  750. Py_DECREF(obj);
  751. }
  752. error:
  753. if (PyErr_Occurred())
  754. PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
  755. }