python.c 25 KB

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