]> git.lizzy.rs Git - plan9front.git/blob - sys/include/dtracy.h
dpost prologue: update /radicalex to fix square displacement (thanks umbraticus and...
[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         DTMAXAGGBUF = 16,
14         
15         DTBUFSZ = 65536,
16         DTANUMBUCKETS = 1024,
17         DTABUCKETS = DTBUFSZ - 4 * DTANUMBUCKETS,
18 };
19 #define DTANIL ((u32int)-1)
20
21 typedef struct DTProbe DTProbe;
22 typedef struct DTExprState DTExprState;
23 typedef struct DTAct DTAct;
24 typedef struct DTActGr DTActGr;
25 typedef struct DTClause DTClause;
26 typedef struct DTEnab DTEnab;
27 typedef struct DTChan DTChan;
28 typedef struct DTExpr DTExpr;
29 typedef struct DTProvider DTProvider;
30 typedef struct DTAgg DTAgg;
31 typedef struct DTBuf DTBuf;
32 typedef struct DTTrigInfo DTTrigInfo;
33
34 /*
35         we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID.
36         we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient.
37         
38         epid == -1 indicates a fault record (see below)
39 */
40 struct DTEnab {
41         u32int epid;
42         DTActGr *gr;
43         DTEnab *probnext, *probprev;
44         DTEnab *channext;
45         DTProbe *prob;
46 };
47
48 /* probes are never freed */
49 struct DTProbe {
50         int nenable;
51         char *name;
52         DTEnab enablist;
53         DTProvider *prov;
54         void *aux; /* for the provider */
55         DTProbe *provnext;
56 };
57
58 struct DTProvider {
59         char *name;
60         /*
61                 provide() is called when the user first uses a provider.
62                 provide() should call dtpnew() to create probes.
63         */
64         void (*provide)(DTProvider *);
65         int (*enable)(DTProbe *); /* enable the probe. return >= 0 for success and < 0 for failure */
66         void (*disable)(DTProbe *); /* disable the probe */
67         
68         /* for the library, not the provider */
69         DTProbe *probes;
70         int provided;
71 };
72
73 /*
74         the dtracy vm is a simple RISC machine with (currently) 16 64-bit registers.
75         all operations are 64-bit.
76
77         instruction encoding:
78         31:24 opcode
79         23:16 a
80         15:8 b
81         7:0 c
82 */
83
84 enum {
85         /* Rc = Ra (op) Rb */
86         DTE_ADD = 0x00,
87         DTE_SUB = 0x01,
88         DTE_MUL = 0x02,
89         DTE_SDIV = 0x03,
90         DTE_SMOD = 0x04,
91         DTE_UDIV = 0x05,
92         DTE_UMOD = 0x06,
93         DTE_AND = 0x07,
94         DTE_OR = 0x08,
95         DTE_XOR = 0x09,
96         DTE_XNOR = 0x0A,
97         DTE_LSL = 0x0B, /* logical shift left */
98         DTE_LSR = 0x0C, /* logical shift right */
99         DTE_ASR = 0x0D, /* arithmetic shift right */
100         DTE_SEQ = 0x10, /* set if equal */
101         DTE_SNE = 0x11, /* set if not equal */
102         DTE_SLT = 0x12, /* set if less than */
103         DTE_SLE = 0x13, /* set if less or equal */
104         
105         /* immediate operations, const = 10 top bits of ab, sign extended and shifted left by 6 bottom bits */
106         DTE_LDI = 0x20, /* Rc = const */
107         DTE_XORI = 0x21, /* Rc = Rc ^ const */
108
109         /* if(Ra (op) Rb) PC += c; */
110         DTE_BEQ = 0x30,
111         DTE_BNE = 0x31,
112         DTE_BLT = 0x32,
113         DTE_BLE = 0x33,
114         
115         DTE_LDV = 0x40, /* R[b] = Var[a] */
116         
117         DTE_ZXT = 0x50, /* R[c] = lower b bits of R[a], zero extended, 0 < b <= 64 */
118         DTE_SXT = 0x51, /* R[c] = lower b bits of R[a], sign extended, 0 < b <= 64 */
119         
120         DTE_RET = 0xF0, /* RET Ra */
121 };
122 #define DTE(op,a,b,c) ((op)<<24|(a)<<16|(b)<<8|(c))
123
124 struct DTExpr {
125         int n;
126         u32int *b;
127 };
128
129 /*
130         aggregation buffers are hashtables and use a different record format.
131         there are DTANUMBUCKETS 4-byte buckets at the end of the buffer.
132         each entry is (link,id,key,val) with a 4-byte link field for the hash chains and a 4-byte aggregation id.
133         
134         the aggregation id actually contains all the data in the DTAgg struct:
135         4-bit type
136         12-bit keysize in qwords
137         16-bit unique id
138         
139         the struct is just for kernel convenience
140 */
141
142 enum {
143         AGGCNT,
144         AGGSUM,
145         AGGAVG,
146         AGGSTD,
147         AGGMIN,
148         AGGMAX,
149 };
150         
151 struct DTAgg {
152         int id;
153         u16int keysize; /* in bytes */
154         u16int recsize;
155         uchar type;
156 };
157
158 /* an action is an expression, plus info about what to do with the result */
159 struct DTAct {
160         enum {
161                 ACTTRACE, /* record the result. size is the number of bytes used. 0 <= size <= 8 */
162                 ACTTRACESTR, /* take the result to be a pointer to a null-terminated string. store it as zero-padded char[size]. */
163                 /*
164                         ACTAGGKEY and ACTAGGVAL together record a value in an aggregation.
165                         they must occur as a pair and targ must point to an already allocated aggregation buffer.
166                         currently 0 <= size <= 8.
167                 */
168                 ACTAGGKEY,
169                 ACTAGGVAL,
170                 ACTCANCEL, /* (must be last action) don't write anything into the main buffer. used to avoid pointless records when using aggregations. */
171         } type;
172         DTExpr *p;
173         int size;
174         DTAgg agg;
175 };
176
177 /* an action group is an optional predicate and a set of actions. */
178 struct DTActGr {
179         u32int id;
180         int ref;
181         DTExpr *pred; /* if non-nil and evaluates to 0, skip the actions. */
182         int nact;
183         DTAct *acts;
184         DTChan *chan;
185         int reclen; /* record size, including 12-byte header */
186 };
187
188 /* a clause lists probe wildcard expressions and an action group. only used during set-up. */
189 struct DTClause {
190         int nprob;
191         char **probs;
192         DTActGr *gr;
193 };
194
195 struct DTBuf {
196         int wr;
197         uchar data[DTBUFSZ];
198 };
199
200 /* a chan is the kernel representation of a client. */
201 struct DTChan {
202         enum {
203                 DTCSTOP,
204                 DTCGO,
205                 DTCFAULT,
206         } state;
207         char errstr[64];
208         u32int epidalloc; /* lowest unused EPID */
209         
210         /* we have 2 buffers per cpu, one for writing and one for reading. dtcread() swaps them if empty. */
211         DTBuf **wrbufs;
212         DTBuf **rdbufs;
213         /* aggregations use separate buffers */
214         DTBuf **aggwrbufs;
215         DTBuf **aggrdbufs;
216         
217         /* list of enablings. */
218         DTEnab *enab;
219 };
220
221 /* this struct collects the state during the execution of a probe */
222 struct DTTrigInfo {
223         /* filled in by caller of dtptrigger */
224         u64int arg[10];
225         /* filled in by dtptrigger */
226         int machno;
227         int epid;
228         u64int ts;
229         DTChan *ch;
230 };
231
232 /* fault records are used to note when a probe had to be aborted (e.g. because of a page fault) */
233 enum {
234         DTFILL = 1, /* illegal address */
235 };
236
237 void dtinit(int);
238 void dtsync(void);
239
240 /* probe functions */
241 DTProbe *dtpnew(char *, DTProvider *, void *aux);
242 int dtpmatch(char *, DTProbe ***);
243 int dtplist(DTProbe ***);
244 void dtptrigger(DTProbe *, DTTrigInfo *);
245
246 /* expression functions */
247 int dteverify(DTExpr *);
248 int dtefmt(Fmt *);
249 #pragma varargck type "I" u32int
250
251 /* action group functions */
252 void dtgpack(Fmt *, DTActGr *);
253 char *dtgunpack(char *, DTActGr **);
254 int dtgverify(DTChan *, DTActGr *);
255 void dtgfree(DTActGr *);
256
257 /* clause functions */
258 void dtclpack(Fmt *, DTClause *);
259 char *dtclunpack(char *, DTClause **);
260 void dtclfree(DTClause *);
261
262 /* chan functions */
263 DTChan *dtcnew(void);
264 void dtcfree(DTChan *);
265 int dtcaddgr(DTChan *, char *, DTActGr *);
266 int dtcaddcl(DTChan *, DTClause *);
267 int dtcread(DTChan *, void *, int);
268 int dtcaggread(DTChan *, void *, int);
269 void dtcreset(DTChan *);
270 void dtcrun(DTChan *, int);
271 int dtcfault(DTTrigInfo *, int, char *, ...);
272
273 /* aggbuf functions */
274 int dtaunpackid(DTAgg *);
275 void dtarecord(DTChan *, int, DTAgg *, uchar *, int, s64int);
276
277 extern DTProvider *dtproviders[];
278 extern int dtnmach;
279
280 /* helper */
281 char *dtstrdup(char *);
282
283 /* these functions are provided by the kernel interface */
284 uvlong dttime(void); /* return current timestamp */
285 void *dtrealloc(void *, ulong);
286 void dtfree(void *);
287 void *dtmalloc(ulong);
288 int dtmachlock(int); /* lock the per-cpu lock */
289 void dtmachunlock(int); /* unlock the per-cpu lock */
290 void dtcoherence(void); /* memory barrier */
291 uvlong dtgetvar(int); /* return the value of a variable */
292 int dtpeek(uvlong, void*, int); /* safe memmemove(). returns -1 on error. */
293
294 enum {
295         DTV_ARG0,
296         DTV_ARG1,
297         DTV_ARG2,
298         DTV_ARG3,
299         DTV_ARG4,
300         DTV_ARG5,
301         DTV_ARG6,
302         DTV_ARG7,
303         DTV_ARG8,
304         DTV_ARG9,
305         DTV_PID,
306         DTV_MACHNO,
307         DTV_TIME,
308         DTV_PROBE,
309         DTNVARS,
310 };
311 extern char *dtvarnames[DTNVARS];