]> git.lizzy.rs Git - plan9front.git/blob - sys/include/dtracy.h
merge
[plan9front.git] / sys / include / dtracy.h
1 #pragma lib "libdtracy.a"
2 #pragma src "/sys/src/libdtracy"
3
4 /*
5         triggered probes run in "probe context", which involves grabbing a per-CPU lock using dtmachlock/dtmachunlock.
6         everything else in the library assumes that the calling code has grabbed a global lock (which is done in 9/port/devtracy.c).
7 */
8
9 enum {
10         DTSTRMAX = 256,
11         DTRECMAX = 1024,
12 };
13
14 typedef struct DTName DTName;
15 typedef struct DTProbe DTProbe;
16 typedef struct DTExprState DTExprState;
17 typedef struct DTAct DTAct;
18 typedef struct DTActGr DTActGr;
19 typedef struct DTClause DTClause;
20 typedef struct DTEnab DTEnab;
21 typedef struct DTChan DTChan;
22 typedef struct DTExpr DTExpr;
23 typedef struct DTProvider DTProvider;
24 typedef struct DTBuf DTBuf;
25
26 struct DTName {
27         char *provider;
28         char *function;
29         char *name;
30 };
31
32 /*
33         we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID.
34         we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient.
35 */
36 struct DTEnab {
37         u32int epid;
38         DTActGr *gr;
39         DTEnab *probnext, *probprev;
40         DTEnab *channext;
41         DTProbe *prob;
42 };
43
44 /* probes are never freed */
45 struct DTProbe {
46         int nenable;
47         DTName;
48         DTEnab enablist;
49         DTProvider *prov;
50         void *aux; /* for the provider */
51         DTProbe *provnext;
52 };
53
54 struct DTProvider {
55         char *name;
56         /*
57                 provide() is called when the user asks for a probe that doesn't exist.
58                 provide() should call dtpnew() to create probes.
59                 it can use the DTName as a hint or just create all probes that it knows about.
60                 the provider has to ensure not to create the same probe multiple times.
61         */
62         void (*provide)(DTProvider *, DTName);
63         int (*enable)(DTProbe *); /* enable the probe. return >= 0 for success and < 0 for failure */
64         void (*disable)(DTProbe *); /* disable the probe */
65         
66         /* for the library, not the provider */
67         DTProbe *probes;
68 };
69
70 /*
71         the dtracy vm is a simple RISC machine with (currently) 16 64-bit registers.
72         all operations are 64-bit.
73
74         instruction encoding:
75         31:24 opcode
76         23:16 a
77         15:8 b
78         7:0 c
79 */
80
81 enum {
82         /* Rc = Ra (op) Rb */
83         DTE_ADD = 0x00,
84         DTE_SUB = 0x01,
85         DTE_MUL = 0x02,
86         DTE_SDIV = 0x03,
87         DTE_SMOD = 0x04,
88         DTE_UDIV = 0x05,
89         DTE_UMOD = 0x06,
90         DTE_AND = 0x07,
91         DTE_OR = 0x08,
92         DTE_XOR = 0x09,
93         DTE_XNOR = 0x0A,
94         DTE_LSL = 0x0B, /* logical shift left */
95         DTE_LSR = 0x0C, /* logical shift right */
96         DTE_ASR = 0x0D, /* arithmetic shift right */
97         DTE_SEQ = 0x10, /* set if equal */
98         DTE_SNE = 0x11, /* set if not equal */
99         DTE_SLT = 0x12, /* set if less than */
100         DTE_SLE = 0x13, /* set if less or equal */
101         
102         /* immediate operations, const = 10 top bits of ab, sign extended and shifted left by 6 bottom bits */
103         DTE_LDI = 0x20, /* Rc = const */
104         DTE_XORI = 0x21, /* Rc = Rc ^ const */
105
106         /* if(Ra (op) Rb) PC += c; */
107         DTE_BEQ = 0x30,
108         DTE_BNE = 0x31,
109         DTE_BLT = 0x32,
110         DTE_BLE = 0x33,
111         
112         DTE_LDV = 0x40, /* R[b] = Var[a] */
113         
114         DTE_ZXT = 0x50, /* R[c] = lower b bits of R[a], zero extended, 0 < b <= 64 */
115         DTE_SXT = 0x51, /* R[c] = lower b bits of R[a], sign extended, 0 < b <= 64 */
116         
117         DTE_RET = 0xF0, /* RET Ra */
118 };
119 #define DTE(op,a,b,c) ((op)<<24|(a)<<16|(b)<<8|(c))
120
121 struct DTExpr {
122         int n;
123         u32int *b;
124 };
125
126 /* an action is an expression, plus info about what to do with the result */
127 struct DTAct {
128         enum {
129                 ACTTRACE, /* record the result. size is the number of bytes used. 0 <= size <= 8 */
130                 ACTTRACESTR, /* take the result to be a pointer to a null-terminated string. store it as zero-padded char[size]. */
131         } type;
132         DTExpr *p;
133         int size;
134 };
135
136 /* an action group is an optional predicate and a set of actions. */
137 struct DTActGr {
138         u32int id;
139         int ref;
140         DTExpr *pred; /* if non-nil and evaluates to 0, skip the actions. */
141         int nact;
142         DTAct *acts;
143         DTChan *chan;
144         int reclen; /* record size, including 12-byte header */
145 };
146
147 /* a clause list probe wildcard expressions and an action group. only used during set-up. */
148 struct DTClause {
149         int nprob;
150         char **probs;
151         DTActGr *gr;
152 };
153
154 enum { DTBUFSZ = 65536 };
155 struct DTBuf {
156         int wr;
157         uchar data[DTBUFSZ];
158 };
159
160 /* a chan is the kernel representation of a client. */
161 struct DTChan {
162         enum {
163                 DTCSTOP,
164                 DTCGO,
165                 DTCFAULT,
166         } state;
167         char errstr[64];
168         u32int epidalloc; /* lowest unused EPID */
169         
170         /* we have 2 buffers per cpu, one for writing and one for reading. dtcread() swaps them if empty. */
171         DTBuf **wrbufs;
172         DTBuf **rdbufs;
173         
174         /* list of enablings. */
175         DTEnab *enab;
176 };
177
178 void dtinit(int);
179 void dtsync(void);
180
181 /* probe functions */
182 DTProbe *dtpnew(DTName, DTProvider *, void *aux);
183 int dtpmatch(DTName, DTProbe ***);
184 void dtptrigger(DTProbe *, int, uvlong, uvlong, uvlong, uvlong);
185
186 /* expression functions */
187 int dteverify(DTExpr *);
188 int dtefmt(Fmt *);
189 #pragma varargck type "I" u32int
190
191 /* action group functions */
192 void dtgpack(Fmt *, DTActGr *);
193 char *dtgunpack(char *, DTActGr **);
194 int dtgverify(DTActGr *);
195 void dtgfree(DTActGr *);
196
197 /* clause functions */
198 void dtclpack(Fmt *, DTClause *);
199 char *dtclunpack(char *, DTClause **);
200 void dtclfree(DTClause *);
201
202 /* chan functions */
203 DTChan *dtcnew(void);
204 void dtcfree(DTChan *);
205 int dtcaddgr(DTChan *, DTName, DTActGr *);
206 int dtcaddcl(DTChan *, DTClause *);
207 int dtcread(DTChan *, void *, int);
208 void dtcreset(DTChan *);
209 void dtcrun(DTChan *, int);
210
211 extern DTProvider *dtproviders[];
212 extern int dtnmach;
213
214 /* helper */
215 char *dtstrdup(char *);
216
217 /* these functions are provided by the kernel interface */
218 uvlong dttime(void); /* return current timestamp */
219 void *dtrealloc(void *, ulong);
220 void dtfree(void *);
221 void *dtmalloc(ulong);
222 void dtmachlock(int); /* lock the per-cpu lock */
223 void dtmachunlock(int); /* unlock the per-cpu lock */
224 void dtcoherence(void); /* memory barrier */
225 uvlong dtgetvar(int); /* return the value of a variable */
226 int dtpeek(uvlong, void*, int); /* safe memmemove(). returns -1 on error. */
227
228 enum {
229         DTV_ARG0,
230         DTV_ARG1,
231         DTV_ARG2,
232         DTV_ARG3,
233         DTV_ARG4,
234         DTV_ARG5,
235         DTV_ARG6,
236         DTV_ARG7,
237         DTV_ARG8,
238         DTV_ARG9,
239         DTV_PID,
240         DTV_MACHNO,
241         DTV_TIME,
242         DTV_PROBE,
243         DTNVARS,
244 };
245 extern char *dtvarnames[DTNVARS];