Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | <?xml version="1.0" encoding="ISO-8859-1"?> |
2 | <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" | |
3 | "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ | |
4 | <!ENTITY % defs SYSTEM "/xserver/doc/xml/xserver.ent"> %defs; | |
5 | ]> | |
6 | ||
7 | <article id="Xserver-DTrace"> | |
8 | <articleinfo> | |
9 | <title>Xserver Provider for DTrace</title> | |
10 | <author> | |
11 | <firstname>Alan</firstname><surname>Coopersmith</surname> | |
12 | <affiliation> | |
13 | <orgname>Oracle Corporation</orgname> | |
14 | <orgdiv>Solaris Engineering</orgdiv> | |
15 | </affiliation> | |
16 | </author> | |
17 | <releaseinfo>X Server Version &xserver.version;</releaseinfo> | |
18 | <copyright><year>2005</year><year>2006</year><year>2007</year><year>2010</year> | |
19 | <holder>Oracle and/or its affiliates. All rights reserved.</holder> | |
20 | </copyright> | |
21 | <legalnotice id="copyright"> | |
22 | <para> | |
23 | Permission is hereby granted, free of charge, to any person obtaining a | |
24 | copy of this software and associated documentation files (the "Software"), | |
25 | to deal in the Software without restriction, including without limitation | |
26 | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
27 | and/or sell copies of the Software, and to permit persons to whom the | |
28 | Software is furnished to do so, subject to the following conditions: | |
29 | </para><para> | |
30 | The above copyright notice and this permission notice (including the next | |
31 | paragraph) shall be included in all copies or substantial portions of the | |
32 | Software. | |
33 | </para><para> | |
34 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
35 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
36 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
37 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
38 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
39 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
40 | DEALINGS IN THE SOFTWARE. | |
41 | </para> | |
42 | </legalnotice> | |
43 | </articleinfo> | |
44 | ||
45 | <sect1 id="introduction"> | |
46 | <title>Introduction</title> | |
47 | <para> | |
48 | This page provides details on a | |
49 | <ulink url="http://wikis.sun.com/display/DTrace/Statically+Defined+Tracing+for+User+Applications">statically defined user application tracing provider</ulink> | |
50 | for the | |
51 | <ulink url="http://hub.opensolaris.org/bin/view/Community+Group+dtrace/">DTrace</ulink> | |
52 | facility in <productname>Solaris</productname> 10, | |
53 | <productname>MacOS X</productname> 10.5, and later releases. This | |
54 | provider instruments various points in the X server, to allow | |
55 | tracing what client applications are up to. DTrace probes may be used | |
56 | with <ulink url="http://sourceware.org/systemtap/">SystemTap</ulink> | |
57 | on GNU/Linux systems. | |
58 | </para> | |
59 | ||
60 | <para> | |
61 | The provider was integrated into the X.Org git master repository | |
62 | with Solaris 10 & OpenSolaris support for the Xserver 1.4 release, | |
63 | released in 2007 with X11R7.3. Support for DTrace on MacOS X | |
64 | was added in Xserver 1.7. | |
65 | </para> | |
66 | ||
67 | <para> | |
68 | These probes expose the request and reply structure of the X protocol | |
69 | between clients and the X server, so an understanding of that basic | |
70 | nature will aid in learning how to use these probes. | |
71 | </para> | |
72 | </sect1> | |
73 | ||
74 | <sect1 id="probes"> | |
75 | <title>Available probes</title> | |
76 | ||
77 | <para> | |
78 | Due to the way User-Defined DTrace probes work, arguments to | |
79 | these probes all bear undistinguished names of | |
80 | <parameter>arg0</parameter>, <parameter>arg1</parameter>, | |
81 | <parameter>arg2</parameter>, etc. These tables should help you | |
82 | determine what the real data is for each of the probe arguments. | |
83 | ||
84 | <table id="Probes_and_their_arguments"> | |
85 | <title>Probes and their arguments</title> | |
86 | <tgroup cols='9'> | |
87 | <colspec colname="probe" colwidth="2*"/> | |
88 | <colspec colname="desc" colwidth="3*"/> | |
89 | <colspec colname="arg0" colwidth="1*"/> | |
90 | <colspec colname="arg1" colwidth="1*"/> | |
91 | <colspec colname="arg2" colwidth="1*"/> | |
92 | <colspec colname="arg3" colwidth="1*"/> | |
93 | <colspec colname="arg4" colwidth="1*"/> | |
94 | <colspec colname="arg5" colwidth="1*"/> | |
95 | <colspec colname="arg6" colwidth="1*"/> | |
96 | <spanspec spanname="all" namest="probe" nameend="arg4"/> | |
97 | <thead> | |
98 | <row> | |
99 | <entry>Probe name</entry> | |
100 | <entry>Description</entry> | |
101 | <entry>arg0</entry> | |
102 | <entry>arg1</entry> | |
103 | <entry>arg2</entry> | |
104 | <entry>arg3</entry> | |
105 | <entry>arg4</entry> | |
106 | <entry>arg5</entry> | |
107 | <entry>arg6</entry> | |
108 | </row> | |
109 | </thead> | |
110 | <tbody> | |
111 | <row> | |
112 | <entry spanname="all" class="grouphead">Request Probes</entry> | |
113 | </row> | |
114 | <row> | |
115 | <entry>request-start</entry> | |
116 | <entry>Called just before processing each client request.</entry> | |
117 | <entry><parameter>requestName</parameter></entry> | |
118 | <entry><parameter>requestCode</parameter></entry> | |
119 | <entry><parameter>requestLength</parameter></entry> | |
120 | <entry><parameter>clientId</parameter></entry> | |
121 | <entry><parameter>requestBuffer</parameter></entry> | |
122 | <entry nameend="arg5" class="unused"/> | |
123 | <entry nameend="arg6" class="unused"/> | |
124 | </row> | |
125 | <row> | |
126 | <entry>request-done</entry> | |
127 | <entry>Called just after processing each client request.</entry> | |
128 | <entry><parameter>requestName</parameter></entry> | |
129 | <entry><parameter>requestCode</parameter></entry> | |
130 | <entry><parameter>sequenceNumber</parameter></entry> | |
131 | <entry><parameter>clientId</parameter></entry> | |
132 | <entry><parameter>resultCode</parameter></entry> | |
133 | <entry nameend="arg5" class="unused"/> | |
134 | <entry nameend="arg6" class="unused"/> | |
135 | </row> | |
136 | <row> | |
137 | <entry spanname="all" class="grouphead">Event Probes</entry> | |
138 | </row> | |
139 | <row> | |
140 | <entry>send-event</entry> | |
141 | <entry>Called just before send each event to a client.</entry> | |
142 | <entry><parameter>clientId</parameter></entry> | |
143 | <entry><parameter>eventCode</parameter></entry> | |
144 | <entry><parameter>eventBuffer</parameter></entry> | |
145 | <entry nameend="arg3" class="unused"/> | |
146 | <entry nameend="arg4" class="unused"/> | |
147 | <entry nameend="arg5" class="unused"/> | |
148 | <entry nameend="arg6" class="unused"/> | |
149 | </row> | |
150 | <row> | |
151 | <entry spanname="all" class="grouphead">Client Connection Probes</entry> | |
152 | </row> | |
153 | <row> | |
154 | <entry>client-connect</entry> | |
155 | <entry>Called when a new connection is opened from a client</entry> | |
156 | <entry><parameter>clientId</parameter></entry> | |
157 | <entry><parameter>clientFD</parameter></entry> | |
158 | <entry nameend="arg2" class="unused"/> | |
159 | <entry nameend="arg3" class="unused"/> | |
160 | <entry nameend="arg4" class="unused"/> | |
161 | <entry nameend="arg5" class="unused"/> | |
162 | <entry nameend="arg6" class="unused"/> | |
163 | </row> | |
164 | <row> | |
165 | <entry>client-auth</entry> | |
166 | <entry>Called when client authenticates (normally just after connection opened)</entry> | |
167 | <entry><parameter>clientId</parameter></entry> | |
168 | <entry><parameter>clientAddr</parameter></entry> | |
169 | <entry><parameter>clientPid</parameter></entry> | |
170 | <entry><parameter>clientZoneId</parameter></entry> | |
171 | <entry nameend="arg4" class="unused"/> | |
172 | <entry nameend="arg5" class="unused"/> | |
173 | <entry nameend="arg6" class="unused"/> | |
174 | </row> | |
175 | <row> | |
176 | <entry>client-disconnect</entry> | |
177 | <entry>Called when a client connection is closed</entry> | |
178 | <entry><parameter>clientId</parameter></entry> | |
179 | <entry nameend="arg1" class="unused"/> | |
180 | <entry nameend="arg2" class="unused"/> | |
181 | <entry nameend="arg3" class="unused"/> | |
182 | <entry nameend="arg4" class="unused"/> | |
183 | <entry nameend="arg5" class="unused"/> | |
184 | <entry nameend="arg6" class="unused"/> | |
185 | </row> | |
186 | <row> | |
187 | <entry spanname="all" class="grouphead">Resource Allocation Probes</entry> | |
188 | </row> | |
189 | <row> | |
190 | <entry>resource-alloc</entry> | |
191 | <entry>Called when a new resource (pixmap, gc, colormap, etc.) is allocated</entry> | |
192 | <entry><parameter>resourceId</parameter></entry> | |
193 | <entry><parameter>resourceTypeId</parameter></entry> | |
194 | <entry><parameter>resourceValue</parameter></entry> | |
195 | <entry><parameter>resourceTypeName</parameter></entry> | |
196 | <entry nameend="arg4" class="unused"/> | |
197 | <entry nameend="arg5" class="unused"/> | |
198 | <entry nameend="arg6" class="unused"/> | |
199 | </row> | |
200 | <row> | |
201 | <entry>resource-free</entry> | |
202 | <entry>Called when a resource is freed</entry> | |
203 | <entry><parameter>resourceId</parameter></entry> | |
204 | <entry><parameter>resourceTypeId</parameter></entry> | |
205 | <entry><parameter>resourceValue</parameter></entry> | |
206 | <entry><parameter>resourceTypeName</parameter></entry> | |
207 | <entry nameend="arg4" class="unused"/> | |
208 | <entry nameend="arg5" class="unused"/> | |
209 | <entry nameend="arg6" class="unused"/> | |
210 | </row> | |
211 | <row> | |
212 | <entry spanname="all" class="grouphead">Input API probes</entry> | |
213 | </row> | |
214 | <row> | |
215 | <entry>input-event</entry> | |
216 | <entry>Called when an input event was submitted for processing</entry> | |
217 | <entry><parameter>deviceid</parameter></entry> | |
218 | <entry><parameter>eventtype</parameter></entry> | |
219 | <entry><parameter>button</parameter> or | |
220 | <parameter>keycode</parameter> or | |
221 | <parameter>touchid</parameter></entry> | |
222 | <entry><parameter>flags</parameter></entry> | |
223 | <entry><parameter>nvalues</parameter></entry> | |
224 | <entry><parameter>mask</parameter></entry> | |
225 | <entry><parameter>values</parameter></entry> | |
226 | </row> | |
227 | </tbody> | |
228 | </tgroup> | |
229 | </table> | |
230 | </para> | |
231 | </sect1> | |
232 | ||
233 | <sect1 id="arguments"> | |
234 | <title>Data Available in Probe Arguments</title> | |
235 | ||
236 | <para> | |
237 | To access data in arguments of type <type>string</type>, you will need | |
238 | to use <ulink url="http://wikis.sun.com/display/DTrace/Actions+and+Subroutines#ActionsandSubroutines-{{copyinstr}}"><function>copyinstr()</function></ulink>. | |
239 | To access data buffers referenced via <type>uintptr_t</type>'s, you will | |
240 | need to use <ulink url="http://wikis.sun.com/display/DTrace/Actions+and+Subroutines#ActionsandSubroutines-{{copyin}}"><function>copyin()</function></ulink>. | |
241 | ||
242 | <table id="Probe_Arguments"> | |
243 | <title>Probe Arguments</title> | |
244 | <tgroup cols='3'> | |
245 | <colspec colname="arg" colwidth="2*"/> | |
246 | <colspec colname="type" colwidth="1*"/> | |
247 | <colspec colname="desc" colwidth="7*"/> | |
248 | <thead> | |
249 | <row> | |
250 | <entry>Argument name</entry> | |
251 | <entry>Type</entry> | |
252 | <entry>Description</entry> | |
253 | </row> | |
254 | </thead> | |
255 | <tbody> | |
256 | <row> | |
257 | <entry><parameter>clientAddr</parameter></entry> | |
258 | <entry><type>string</type></entry> | |
259 | <entry>String representing address client connected from</entry> | |
260 | </row> | |
261 | <row> | |
262 | <entry><parameter>clientFD</parameter></entry> | |
263 | <entry><type>int</type></entry> | |
264 | <entry>X server's file descriptor for server side of each connection</entry> | |
265 | </row> | |
266 | <row> | |
267 | <entry><parameter>clientId</parameter></entry> | |
268 | <entry><type>int</type></entry> | |
269 | <entry>Unique integer identifier for each connection to the | |
270 | X server</entry> | |
271 | </row> | |
272 | <row> | |
273 | <entry><parameter>clientPid</parameter></entry> | |
274 | <entry><type>pid_t</type></entry> | |
275 | <entry>Process id of client, if connection is local | |
276 | (from <function>getpeerucred()</function>)</entry> | |
277 | </row> | |
278 | <row> | |
279 | <entry><parameter>clientZoneId</parameter></entry> | |
280 | <entry><type>zoneid_t</type></entry> | |
281 | <entry>Solaris: Zone id of client, if connection is local | |
282 | (from <function>getpeerucred()</function>)</entry> | |
283 | </row> | |
284 | <row> | |
285 | <entry><parameter>eventBuffer</parameter></entry> | |
286 | <entry><type>uintptr_t</type></entry> | |
287 | <entry>Pointer to buffer containing X event - decode using | |
288 | structures in | |
289 | <<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>> | |
290 | and similar headers for each extension</entry> | |
291 | </row> | |
292 | <row> | |
293 | <entry><parameter>eventCode</parameter></entry> | |
294 | <entry><type>uint8_t</type></entry> | |
295 | <entry>Event number of X event</entry> | |
296 | </row> | |
297 | <row> | |
298 | <entry><parameter>resourceId</parameter></entry> | |
299 | <entry><type>uint32_t</type></entry> | |
300 | <entry>X resource id (XID)</entry> | |
301 | </row> | |
302 | <row> | |
303 | <entry><parameter>resourceTypeId</parameter></entry> | |
304 | <entry><type>uint32_t</type></entry> | |
305 | <entry>Resource type id</entry> | |
306 | </row> | |
307 | <row> | |
308 | <entry><parameter>resourceTypeName</parameter></entry> | |
309 | <entry><type>string</type></entry> | |
310 | <entry>String representing X resource type | |
311 | (<literal>"PIXMAP"</literal>, etc.)</entry> | |
312 | </row> | |
313 | <row> | |
314 | <entry><parameter>resourceValue</parameter></entry> | |
315 | <entry><type>uintptr_t</type></entry> | |
316 | <entry>Pointer to data for X resource</entry> | |
317 | </row> | |
318 | <row> | |
319 | <entry><parameter>resultCode</parameter></entry> | |
320 | <entry><type>int</type></entry> | |
321 | <entry>Integer code representing result status of request</entry> | |
322 | </row> | |
323 | <row> | |
324 | <entry><parameter>requestBuffer</parameter></entry> | |
325 | <entry><type>uintptr_t</type></entry> | |
326 | <entry>Pointer to buffer containing X request - decode using | |
327 | structures in | |
328 | <<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>> | |
329 | and similar headers for each extension</entry> | |
330 | </row> | |
331 | <row> | |
332 | <entry><parameter>requestCode</parameter></entry> | |
333 | <entry><type>uint8_t</type></entry> | |
334 | <entry>Request number of X request or Extension</entry> | |
335 | </row> | |
336 | <row> | |
337 | <entry><parameter>requestName</parameter></entry> | |
338 | <entry><type>string</type></entry> | |
339 | <entry>Name of X request or Extension</entry> | |
340 | </row> | |
341 | <row> | |
342 | <entry><parameter>requestLength</parameter></entry> | |
343 | <entry><type>uint16_t</type></entry> | |
344 | <entry>Length of X request</entry> | |
345 | </row> | |
346 | <row> | |
347 | <entry><parameter>sequenceNumber</parameter></entry> | |
348 | <entry><type>uint32_t</type></entry> | |
349 | <entry>Number of X request in in this connection</entry> | |
350 | </row> | |
351 | <row> | |
352 | <entry><parameter>deviceid</parameter></entry> | |
353 | <entry><type>int</type></entry> | |
354 | <entry>The device's numerical ID</entry> | |
355 | </row> | |
356 | <row> | |
357 | <entry><parameter>eventtype</parameter></entry> | |
358 | <entry><type>int</type></entry> | |
359 | <entry>Protocol event type</entry> | |
360 | </row> | |
361 | <row> | |
362 | <entry><parameter>button, keycode, touchid</parameter></entry> | |
363 | <entry><type>uint32_t</type></entry> | |
364 | <entry>The button number, keycode or touch ID</entry> | |
365 | </row> | |
366 | <row> | |
367 | <entry><parameter>flags</parameter></entry> | |
368 | <entry><type>uint32_t</type></entry> | |
369 | <entry>Miscellaneous event-specific server flags</entry> | |
370 | </row> | |
371 | <row> | |
372 | <entry><parameter>nvalues</parameter></entry> | |
373 | <entry><type>int8_t</type></entry> | |
374 | <entry>Number of bits in <parameter>mask</parameter> and number of elements | |
375 | in <parameter>values</parameter></entry> | |
376 | </row> | |
377 | <row> | |
378 | <entry><parameter>mask</parameter></entry> | |
379 | <entry><type>uint8_t*</type></entry> | |
380 | <entry>Binary mask indicating which indices in <parameter>values</parameter> contain | |
381 | valid data</entry> | |
382 | </row> | |
383 | <row> | |
384 | <entry><parameter>values</parameter></entry> | |
385 | <entry><type>double*</type></entry> | |
386 | <entry>Valuator values. Values for indices for which the | |
387 | <parameter>mask</parameter> is not set are undefined</entry> | |
388 | </row> | |
389 | </tbody> | |
390 | </tgroup> | |
391 | </table> | |
392 | </para> | |
393 | </sect1> | |
394 | ||
395 | <sect1 id="examples"> | |
396 | <title>Examples</title> | |
397 | ||
398 | <example id="Counting_requests_by_request_name"> | |
399 | <title>Counting requests by request name</title> | |
400 | ||
401 | <para> | |
402 | This script simply increments a counter for each different request | |
403 | made, and when you exit the script (such as by hitting | |
404 | <keycombo action='simul'><keycap>Control</keycap><keycap>C</keycap> | |
405 | </keycombo>) prints the counts. | |
406 | ||
407 | <programlisting> | |
408 | #!/usr/sbin/dtrace -s | |
409 | ||
410 | Xserver*:::request-start | |
411 | { | |
412 | @counts[copyinstr(arg0)] = count(); | |
413 | } | |
414 | </programlisting> | |
415 | ||
416 | The output from a short run may appear as: | |
417 | <screen> | |
418 | QueryPointer 1 | |
419 | CreatePixmap 2 | |
420 | FreePixmap 2 | |
421 | PutImage 2 | |
422 | ChangeGC 10 | |
423 | CopyArea 10 | |
424 | CreateGC 14 | |
425 | FreeGC 14 | |
426 | RENDER 28 | |
427 | SetClipRectangles 40 | |
428 | </screen> | |
429 | </para> | |
430 | ||
431 | <para> | |
432 | This can be rewritten slightly to cache the string containing the name | |
433 | of the request since it will be reused many times, instead of copying | |
434 | it over and over from the kernel: | |
435 | ||
436 | <programlisting> | |
437 | #!/usr/sbin/dtrace -s | |
438 | ||
439 | string Xrequest[uintptr_t]; | |
440 | ||
441 | Xserver*:::request-start | |
442 | /Xrequest[arg0] == ""/ | |
443 | { | |
444 | Xrequest[arg0] = copyinstr(arg0); | |
445 | } | |
446 | ||
447 | Xserver*:::request-start | |
448 | { | |
449 | @counts[Xrequest[arg0]] = count(); | |
450 | } | |
451 | </programlisting> | |
452 | </para> | |
453 | </example> | |
454 | ||
455 | <example id="Get_average_CPU_time_per_request"> | |
456 | <title>Get average CPU time per request</title> | |
457 | ||
458 | <para>This script records the CPU time used between the probes at | |
459 | the start and end of each request and aggregates it per request type. | |
460 | ||
461 | <programlisting> | |
462 | #!/usr/sbin/dtrace -s | |
463 | ||
464 | Xserver*:::request-start | |
465 | { | |
466 | reqstart = vtimestamp; | |
467 | } | |
468 | ||
469 | Xserver*:::request-done | |
470 | { | |
471 | @times[copyinstr(arg0)] = avg(vtimestamp - reqstart); | |
472 | } | |
473 | </programlisting> | |
474 | ||
475 | The output from a sample run might look like: | |
476 | ||
477 | <screen> | |
478 | ChangeGC 889 | |
479 | MapWindow 907 | |
480 | SetClipRectangles 1319 | |
481 | PolyPoint 1413 | |
482 | PolySegment 1434 | |
483 | PolyRectangle 1828 | |
484 | FreeCursor 1895 | |
485 | FreeGC 1950 | |
486 | CreateGC 2244 | |
487 | FreePixmap 2246 | |
488 | GetInputFocus 2249 | |
489 | TranslateCoords 8508 | |
490 | QueryTree 8846 | |
491 | GetGeometry 9948 | |
492 | CreatePixmap 12111 | |
493 | AllowEvents 14090 | |
494 | GrabServer 14791 | |
495 | MIT-SCREEN-SAVER 16747 | |
496 | ConfigureWindow 22917 | |
497 | SetInputFocus 28521 | |
498 | PutImage 240841 | |
499 | ||
500 | </screen> | |
501 | </para> | |
502 | </example> | |
503 | ||
504 | <example id="Monitoring_clients_that_connect_and_disconnect"> | |
505 | <title>Monitoring clients that connect and disconnect</title> | |
506 | ||
507 | <para> | |
508 | This script simply prints information about each client that | |
509 | connects or disconnects from the server while it is running. | |
510 | Since the provider is specified as <code>Xserver$1</code> instead | |
511 | of <code>Xserver*</code> like previous examples, it won't monitor | |
512 | all Xserver processes running on the machine, but instead expects | |
513 | the process id of the X server to monitor to be specified as the | |
514 | argument to the script. | |
515 | ||
516 | <programlisting> | |
517 | #!/usr/sbin/dtrace -s | |
518 | ||
519 | Xserver$1:::client-connect | |
520 | { | |
521 | printf("** Client Connect: id %d\n", arg0); | |
522 | } | |
523 | ||
524 | Xserver$1:::client-auth | |
525 | { | |
526 | printf("** Client auth'ed: id %d => %s pid %d\n", | |
527 | arg0, copyinstr(arg1), arg2); | |
528 | } | |
529 | ||
530 | Xserver$1:::client-disconnect | |
531 | { | |
532 | printf("** Client Disconnect: id %d\n", arg0); | |
533 | } | |
534 | </programlisting> | |
535 | ||
536 | A sample run: | |
537 | ||
538 | <screen> | |
539 | <prompt>#</prompt> <userinput>./foo.d 5790</userinput> | |
540 | <computeroutput>dtrace: script './foo.d' matched 4 probes | |
541 | CPU ID FUNCTION:NAME | |
542 | 0 15774 CloseDownClient:client-disconnect ** Client Disconnect: id 65 | |
543 | ||
544 | 2 15774 CloseDownClient:client-disconnect ** Client Disconnect: id 64 | |
545 | ||
546 | 0 15773 EstablishNewConnections:client-connect ** Client Connect: id 64 | |
547 | ||
548 | 0 15772 AuthAudit:client-auth ** Client auth'ed: id 64 => local host pid 2034 | |
549 | ||
550 | 0 15773 EstablishNewConnections:client-connect ** Client Connect: id 65 | |
551 | ||
552 | 0 15772 AuthAudit:client-auth ** Client auth'ed: id 65 => local host pid 2034 | |
553 | ||
554 | 0 15774 CloseDownClient:client-disconnect ** Client Disconnect: id 64 | |
555 | </computeroutput> | |
556 | </screen> | |
557 | ||
558 | </para> | |
559 | </example> | |
560 | ||
561 | <example id="Monitoring_clients_creating_Pixmaps"> | |
562 | <title>Monitoring clients creating Pixmaps</title> | |
563 | ||
564 | <para> | |
565 | This script can be used to determine which clients are creating | |
566 | pixmaps in the X server, printing information about each client | |
567 | as it connects to help trace it back to the program on the other | |
568 | end of the X connection. | |
569 | ||
570 | <programlisting> | |
571 | #!/usr/sbin/dtrace -qs | |
572 | ||
573 | string Xrequest[uintptr_t]; | |
574 | string Xrestype[uintptr_t]; | |
575 | ||
576 | Xserver$1:::request-start | |
577 | /Xrequest[arg0] == ""/ | |
578 | { | |
579 | Xrequest[arg0] = copyinstr(arg0); | |
580 | } | |
581 | ||
582 | Xserver$1:::resource-alloc | |
583 | /arg3 != 0 && Xrestype[arg3] == ""/ | |
584 | { | |
585 | Xrestype[arg3] = copyinstr(arg3); | |
586 | } | |
587 | ||
588 | ||
589 | Xserver$1:::request-start | |
590 | /Xrequest[arg0] == "X_CreatePixmap"/ | |
591 | { | |
592 | printf("-> %s: client %d\n", Xrequest[arg0], arg3); | |
593 | } | |
594 | ||
595 | Xserver$1:::request-done | |
596 | /Xrequest[arg0] == "X_CreatePixmap"/ | |
597 | { | |
598 | printf("<- %s: client %d\n", Xrequest[arg0], arg3); | |
599 | } | |
600 | ||
601 | Xserver$1:::resource-alloc | |
602 | /Xrestype[arg3] == "PIXMAP"/ | |
603 | { | |
604 | printf("** Pixmap alloc: %08x\n", arg0); | |
605 | } | |
606 | ||
607 | ||
608 | Xserver$1:::resource-free | |
609 | /Xrestype[arg3] == "PIXMAP"/ | |
610 | { | |
611 | printf("** Pixmap free: %08x\n", arg0); | |
612 | } | |
613 | ||
614 | Xserver$1:::client-connect | |
615 | { | |
616 | printf("** Client Connect: id %d\n", arg0); | |
617 | } | |
618 | ||
619 | Xserver$1:::client-auth | |
620 | { | |
621 | printf("** Client auth'ed: id %d => %s pid %d\n", | |
622 | arg0, copyinstr(arg1), arg2); | |
623 | } | |
624 | ||
625 | Xserver$1:::client-disconnect | |
626 | { | |
627 | printf("** Client Disconnect: id %d\n", arg0); | |
628 | } | |
629 | </programlisting> | |
630 | ||
631 | Sample output from a run of this script: | |
632 | <screen><computeroutput> | |
633 | ** Client Connect: id 17 | |
634 | ** Client auth'ed: id 17 => local host pid 20273 | |
635 | -> X_CreatePixmap: client 17 | |
636 | ** Pixmap alloc: 02200009 | |
637 | <- X_CreatePixmap: client 17 | |
638 | -> X_CreatePixmap: client 15 | |
639 | ** Pixmap alloc: 01e00180 | |
640 | <- X_CreatePixmap: client 15 | |
641 | -> X_CreatePixmap: client 15 | |
642 | ** Pixmap alloc: 01e00181 | |
643 | <- X_CreatePixmap: client 15 | |
644 | -> X_CreatePixmap: client 14 | |
645 | ** Pixmap alloc: 01c004c8 | |
646 | <- X_CreatePixmap: client 14 | |
647 | ** Pixmap free: 02200009 | |
648 | ** Client Disconnect: id 17 | |
649 | ** Pixmap free: 01e00180 | |
650 | ** Pixmap free: 01e00181 | |
651 | </computeroutput></screen> | |
652 | ||
653 | </para> | |
654 | ||
655 | </example> | |
656 | ||
657 | <example id="Input_API_monitoring_with_systemtap"> | |
658 | <title>Input API monitoring with SystemTap</title> | |
659 | ||
660 | <para> | |
661 | This script can be used to monitor events submitted by drivers to | |
662 | the server for enqueuing. Due to the integration of the input API | |
663 | probes, some server-enqueued events will show up too. | |
664 | <programlisting> | |
665 | # Compile+run with | |
666 | # stap -g xorg.stp /usr/bin/Xorg | |
667 | # | |
668 | ||
669 | ||
670 | function print_valuators:string(nvaluators:long, mask_in:long, valuators_in:long) %{ | |
671 | int i; | |
672 | unsigned char *mask = (unsigned char*)THIS->mask_in; | |
673 | double *valuators = (double*)THIS->valuators_in; | |
674 | char str[128] = {0}; | |
675 | char *s = str; | |
676 | ||
677 | #define BitIsSet(ptr, bit) (((unsigned char*)(ptr))[(bit)>>3] & (1 << ((bit) & 7))) | |
678 | ||
679 | s += sprintf(s, "nval: %d ::", (int)THIS->nvaluators); | |
680 | for (i = 0; i < THIS->nvaluators; i++) | |
681 | { | |
682 | s += sprintf(s, " %d: ", i); | |
683 | if (BitIsSet(mask, i)) | |
684 | s += sprintf(s, "%d", (int)valuators[i]); | |
685 | } | |
686 | ||
687 | sprintf(THIS->__retvalue, "%s", str); | |
688 | %} | |
689 | ||
690 | probe process(@1).mark("input__event") | |
691 | { | |
692 | deviceid = $arg1 | |
693 | type = $arg2 | |
694 | detail = $arg3 | |
695 | flags = $arg4 | |
696 | nvaluators = $arg5 | |
697 | ||
698 | str = print_valuators(nvaluators, $arg6, $arg7) | |
699 | printf("Event: device %d type %d detail %d flags %#x %s\n", | |
700 | deviceid, type, detail, flags, str); | |
701 | } | |
702 | </programlisting> | |
703 | ||
704 | Sample output from a run of this script: | |
705 | <screen><computeroutput> | |
706 | Event: device 13 type 4 detail 1 flags 0x0 nval: 0 :: | |
707 | Event: device 13 type 6 detail 0 flags 0xa nval: 1 :: 0: 1 | |
708 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -1 | |
709 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -1 | |
710 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 4 1: -3 | |
711 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 3 1: -3 | |
712 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 3 1: -2 | |
713 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -2 | |
714 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -2 | |
715 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -2 | |
716 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 1: -1 | |
717 | Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 1: -1 | |
718 | Event: device 13 type 5 detail 1 flags 0x0 nval: 0 :: | |
719 | </computeroutput></screen> | |
720 | ||
721 | </para> | |
722 | ||
723 | </example> | |
724 | ||
725 | </sect1> | |
726 | ||
727 | </article> |