xref: /aosp_15_r20/external/bcc/examples/cpp/pyperf/PyPerfType.h (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 /*
2  * Copyright (c) Facebook, Inc.
3  * Licensed under the Apache License, Version 2.0 (the "License")
4  */
5 
6 #pragma once
7 
8 #include <sys/types.h>
9 #include <cstdint>
10 #include <string>
11 #include <vector>
12 
13 #define PYTHON_STACK_FRAMES_PER_PROG 25
14 #define PYTHON_STACK_PROG_CNT 3
15 #define STACK_MAX_LEN (PYTHON_STACK_FRAMES_PER_PROG * PYTHON_STACK_PROG_CNT)
16 #define CLASS_NAME_LEN 32
17 #define FUNCTION_NAME_LEN 64
18 #define FILE_NAME_LEN 128
19 #define TASK_COMM_LEN 16
20 
21 namespace ebpf {
22 namespace pyperf {
23 
24 enum {
25   STACK_STATUS_COMPLETE = 0,
26   STACK_STATUS_ERROR = 1,
27   STACK_STATUS_TRUNCATED = 2,
28 };
29 
30 enum {
31   GIL_STATE_NO_INFO = 0,
32   GIL_STATE_ERROR = 1,
33   GIL_STATE_UNINITIALIZED = 2,
34   GIL_STATE_NOT_LOCKED = 3,
35   GIL_STATE_THIS_THREAD = 4,
36   GIL_STATE_GLOBAL_CURRENT_THREAD = 5,
37   GIL_STATE_OTHER_THREAD = 6,
38   GIL_STATE_NULL = 7,
39 };
40 
41 enum {
42   THREAD_STATE_UNKNOWN = 0,
43   THREAD_STATE_MATCH = 1,
44   THREAD_STATE_MISMATCH = 2,
45   THREAD_STATE_THIS_THREAD_NULL = 3,
46   THREAD_STATE_GLOBAL_CURRENT_THREAD_NULL = 4,
47   THREAD_STATE_BOTH_NULL = 5,
48 };
49 
50 enum {
51   PTHREAD_ID_UNKNOWN = 0,
52   PTHREAD_ID_MATCH = 1,
53   PTHREAD_ID_MISMATCH = 2,
54   PTHREAD_ID_THREAD_STATE_NULL = 3,
55   PTHREAD_ID_NULL = 4,
56   PTHREAD_ID_ERROR = 5,
57 };
58 
59 typedef struct {
60   int64_t PyObject_type;
61   int64_t PyTypeObject_name;
62   int64_t PyThreadState_frame;
63   int64_t PyThreadState_thread;
64   int64_t PyFrameObject_back;
65   int64_t PyFrameObject_code;
66   int64_t PyFrameObject_lineno;
67   int64_t PyFrameObject_localsplus;
68   int64_t PyCodeObject_filename;
69   int64_t PyCodeObject_name;
70   int64_t PyCodeObject_varnames;
71   int64_t PyTupleObject_item;
72   int64_t String_data;
73   int64_t String_size;
74 } OffsetConfig;
75 
76 typedef struct {
77   uintptr_t current_state_addr;  // virtual address of _PyThreadState_Current
78   uintptr_t tls_key_addr;     // virtual address of autoTLSkey for pthreads TLS
79   uintptr_t gil_locked_addr;  // virtual address of gil_locked
80   uintptr_t gil_last_holder_addr;  // virtual address of gil_last_holder
81   OffsetConfig offsets;
82 } PidData;
83 
84 typedef struct {
85   char classname[CLASS_NAME_LEN];
86   char name[FUNCTION_NAME_LEN];
87   char file[FILE_NAME_LEN];
88   // NOTE: PyFrameObject also has line number but it is typically just the
89   // first line of that function and PyCode_Addr2Line needs to be called
90   // to get the actual line
91 } Symbol;
92 
93 typedef struct {
94   uint32_t pid;
95   uint32_t tid;
96   char comm[TASK_COMM_LEN];
97   uint8_t thread_state_match;
98   uint8_t gil_state;
99   uint8_t pthread_id_match;
100   uint8_t stack_status;
101   // instead of storing symbol name here directly, we add it to another
102   // hashmap with Symbols and only store the ids here
103   int64_t stack_len;
104   int32_t stack[STACK_MAX_LEN];
105 } Event;
106 
107 struct PyPerfSample {
108   pid_t pid;
109   pid_t tid;
110   std::string comm;
111   uint8_t threadStateMatch;
112   uint8_t gilState;
113   uint8_t pthreadIDMatch;
114   uint8_t stackStatus;
115   std::vector<int32_t> pyStackIds;
116 
PyPerfSamplePyPerfSample117   explicit PyPerfSample(const Event* raw, int rawSize)
118       : pid(raw->pid),
119         tid(raw->tid),
120         comm(raw->comm),
121         threadStateMatch(raw->thread_state_match),
122         gilState(raw->gil_state),
123         pthreadIDMatch(raw->pthread_id_match),
124         stackStatus(raw->stack_status),
125         pyStackIds(raw->stack, raw->stack + raw->stack_len) {}
126 };
127 
128 }  // namespace pyperf
129 }  // namespace ebpf
130