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.Org Xserver version &xserver.version;</releaseinfo>
18    <legalnotice id="copyright">
19      <para>
20Copyright (c) 2005, 2006, 2007, 2010, Oracle and/or its affiliates.
21All rights reserved.
22      </para><para>
23Permission is hereby granted, free of charge, to any person obtaining a
24copy of this software and associated documentation files (the "Software"),
25to deal in the Software without restriction, including without limitation
26the rights to use, copy, modify, merge, publish, distribute, sublicense,
27and/or sell copies of the Software, and to permit persons to whom the
28Software is furnished to do so, subject to the following conditions:
29      </para><para>
30The above copyright notice and this permission notice (including the next
31paragraph) shall be included in all copies or substantial portions of the
32Software.
33      </para><para>
34THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
37THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
39FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
40DEALINGS 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.
56    </para>
57
58    <para>
59      The provider was integrated into the X.Org git master repository
60      with Solaris 10 &amp; OpenSolaris support for the Xserver 1.4 release,
61      released in 2007 with X11R7.3.   Support for DTrace on MacOS X
62      was added in Xserver 1.7.
63    </para>
64
65    <para>
66      These probes expose the request and reply structure of the X protocol
67      between clients and the X server, so an understanding of that basic
68      nature will aid in learning how to use these probes.
69    </para>
70  </sect1>
71
72  <sect1 id="probes">
73    <title>Available probes</title>
74
75    <para>
76      Due to the way User-Defined DTrace probes work, arguments to
77      these probes all bear undistinguished names of
78      <parameter>arg0</parameter>, <parameter>arg1</parameter>,
79      <parameter>arg2</parameter>, etc.  These tables should help you
80      determine what the real data is for each of the probe arguments.
81
82    <table id="Probes_and_their_arguments">
83      <title>Probes and their arguments</title>
84      <tgroup cols='7'>
85	<colspec colname="probe" colwidth="2*"/>
86	<colspec colname="desc" colwidth="3*"/>
87	<colspec colname="arg0" colwidth="1*"/>
88	<colspec colname="arg1" colwidth="1*"/>
89	<colspec colname="arg2" colwidth="1*"/>
90	<colspec colname="arg3" colwidth="1*"/>
91	<colspec colname="arg4" colwidth="1*"/>
92	<spanspec spanname="all" namest="probe" nameend="arg4"/>
93	<thead>
94	  <row>
95	    <entry>Probe name</entry>
96	    <entry>Description</entry>
97	    <entry>arg0</entry>
98	    <entry>arg1</entry>
99	    <entry>arg2</entry>
100	    <entry>arg3</entry>
101	    <entry>arg4</entry>
102	  </row>
103	</thead>
104	<tbody>
105	  <row>
106	    <entry spanname="all" class="grouphead">Request Probes</entry>
107	  </row>
108	  <row>
109	    <entry>request-start</entry>
110	    <entry>Called just before processing each client request.</entry>
111	    <entry><parameter>requestName</parameter></entry>
112	    <entry><parameter>requestCode</parameter></entry>
113	    <entry><parameter>requestLength</parameter></entry>
114	    <entry><parameter>clientId</parameter></entry>
115	    <entry><parameter>requestBuffer</parameter></entry>
116	  </row>
117	  <row>
118	    <entry>request-done</entry>
119	    <entry>Called just after processing each client request.</entry>
120	    <entry><parameter>requestName</parameter></entry>
121	    <entry><parameter>requestCode</parameter></entry>
122	    <entry><parameter>sequenceNumber</parameter></entry>
123	    <entry><parameter>clientId</parameter></entry>
124	    <entry><parameter>resultCode</parameter></entry>
125	  </row>
126	  <row>
127	    <entry spanname="all" class="grouphead">Event Probes</entry>
128	  </row>
129	  <row>
130	    <entry>send-event</entry>
131	    <entry>Called just before send each event to a client.</entry>
132	    <entry><parameter>clientId</parameter></entry>
133	    <entry><parameter>eventCode</parameter></entry>
134	    <entry><parameter>eventBuffer</parameter></entry>
135	    <entry nameend="arg4" class="unused"/>
136	  </row>
137	  <row>
138	    <entry spanname="all" class="grouphead">Client Connection Probes</entry>
139	  </row>
140	  <row>
141	    <entry>client-connect</entry>
142	    <entry>Called when a new connection is opened from a client</entry>
143	    <entry><parameter>clientId</parameter></entry>
144	    <entry><parameter>clientFD</parameter></entry>
145	    <entry nameend="arg4" class="unused"/>
146	  </row>
147	  <row>
148	    <entry>client-auth</entry>
149	    <entry>Called when client authenticates (normally just after connection opened)</entry>
150	    <entry><parameter>clientId</parameter></entry>
151	    <entry><parameter>clientAddr</parameter></entry>
152	    <entry><parameter>clientPid</parameter></entry>
153	    <entry><parameter>clientZoneId</parameter></entry>
154	    <entry nameend="arg4" class="unused"/>
155	  </row>
156	  <row>
157	    <entry>client-disconnect</entry>
158	    <entry>Called when a client connection is closed</entry>
159	    <entry><parameter>clientId</parameter></entry>
160	    <entry nameend="arg4" class="unused"/>
161	  </row>
162	  <row>
163	    <entry spanname="all" class="grouphead">Resource Allocation Probes</entry>
164	  </row>
165	  <row>
166	    <entry>resource-alloc</entry>
167	    <entry>Called when a new resource (pixmap, gc, colormap, etc.) is allocated</entry>
168	    <entry><parameter>resourceId</parameter></entry>
169	    <entry><parameter>resourceTypeId</parameter></entry>
170	    <entry><parameter>resourceValue</parameter></entry>
171	    <entry><parameter>resourceTypeName</parameter></entry>
172	    <entry nameend="arg4" class="unused"/>
173	  </row>
174	  <row>
175	    <entry>resource-free</entry>
176	    <entry>Called when a resource is freed</entry>
177	    <entry><parameter>resourceId</parameter></entry>
178	    <entry><parameter>resourceTypeId</parameter></entry>
179	    <entry><parameter>resourceValue</parameter></entry>
180	    <entry><parameter>resourceTypeName</parameter></entry>
181	    <entry nameend="arg4" class="unused"/>
182	  </row>
183	</tbody>
184      </tgroup>
185    </table>
186    </para>
187  </sect1>
188
189  <sect1 id="arguments">
190    <title>Data Available in Probe Arguments</title>
191
192    <para>
193      To access data in arguments of type <type>string</type>, you will need
194      to use <ulink url="http://wikis.sun.com/display/DTrace/Actions+and+Subroutines#ActionsandSubroutines-{{copyinstr}}"><function>copyinstr()</function></ulink>.
195      To access data buffers referenced via <type>uintptr_t</type>'s, you will
196      need to use <ulink url="http://wikis.sun.com/display/DTrace/Actions+and+Subroutines#ActionsandSubroutines-{{copyin}}"><function>copyin()</function></ulink>.
197
198    <table id="Probe_Arguments">
199      <title>Probe Arguments</title>
200      <tgroup cols='3'>
201	<colspec colname="arg" colwidth="2*"/>
202	<colspec colname="type" colwidth="1*"/>
203	<colspec colname="desc" colwidth="7*"/>
204	<thead>
205	  <row>
206	    <entry>Argument name</entry>
207	    <entry>Type</entry>
208	    <entry>Description</entry>
209	  </row>
210	</thead>
211	<tbody>
212	  <row>
213	    <entry><parameter>clientAddr</parameter></entry>
214	    <entry><type>string</type></entry>
215	    <entry>String representing address client connected from</entry>
216	  </row>
217	  <row>
218	    <entry><parameter>clientFD</parameter></entry>
219	    <entry><type>int</type></entry>
220	    <entry>X server's file descriptor for server side of each connection</entry>
221	  </row>
222	  <row>
223	    <entry><parameter>clientId</parameter></entry>
224	    <entry><type>int</type></entry>
225	    <entry>Unique integer identifier for each connection to the
226	      X server</entry>
227	  </row>
228	  <row>
229	    <entry><parameter>clientPid</parameter></entry>
230	    <entry><type>pid_t</type></entry>
231	    <entry>Process id of client, if connection is local
232	      (from <function>getpeerucred()</function>)</entry>
233	  </row>
234	  <row>
235	    <entry><parameter>clientZoneId</parameter></entry>
236	    <entry><type>zoneid_t</type></entry>
237	    <entry>Solaris: Zone id of client, if connection is local
238	      (from <function>getpeerucred()</function>)</entry>
239	  </row>
240	  <row>
241	    <entry><parameter>eventBuffer</parameter></entry>
242	    <entry><type>uintptr_t</type></entry>
243	    <entry>Pointer to buffer containing X event - decode using
244	      structures in
245	      &lt;<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>&gt;
246	      and similar headers for each extension</entry>
247	  </row>
248	  <row>
249	    <entry><parameter>eventCode</parameter></entry>
250	    <entry><type>uint8_t</type></entry>
251	    <entry>Event number of X event</entry>
252	  </row>
253	  <row>
254	    <entry><parameter>resourceId</parameter></entry>
255	    <entry><type>uint32_t</type></entry>
256	    <entry>X resource id (XID)</entry>
257	  </row>
258	  <row>
259	    <entry><parameter>resourceTypeId</parameter></entry>
260	    <entry><type>uint32_t</type></entry>
261	    <entry>Resource type id</entry>
262	  </row>
263	  <row>
264	    <entry><parameter>resourceTypeName</parameter></entry>
265	    <entry><type>string</type></entry>
266	    <entry>String representing X resource type
267		(<literal>"PIXMAP"</literal>, etc.)</entry>
268	  </row>
269	  <row>
270	    <entry><parameter>resourceValue</parameter></entry>
271	    <entry><type>uintptr_t</type></entry>
272	    <entry>Pointer to data for X resource</entry>
273	  </row>
274	  <row>
275	    <entry><parameter>resultCode</parameter></entry>
276	    <entry><type>int</type></entry>
277	    <entry>Integer code representing result status of request</entry>
278	  </row>
279	  <row>
280	    <entry><parameter>requestBuffer</parameter></entry>
281	    <entry><type>uintptr_t</type></entry>
282	    <entry>Pointer to buffer containing X request - decode using
283	      structures in
284	      &lt;<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>&gt;
285	      and similar headers for each extension</entry>
286	  </row>
287	  <row>
288	    <entry><parameter>requestCode</parameter></entry>
289	    <entry><type>uint8_t</type></entry>
290	    <entry>Request number of X request or Extension</entry>
291	  </row>
292	  <row>
293	    <entry><parameter>requestName</parameter></entry>
294	    <entry><type>string</type></entry>
295	    <entry>Name of X request or Extension</entry>
296	  </row>
297	  <row>
298	    <entry><parameter>requestLength</parameter></entry>
299	    <entry><type>uint16_t</type></entry>
300	    <entry>Length of X request</entry>
301	  </row>
302	  <row>
303	    <entry><parameter>sequenceNumber</parameter></entry>
304	    <entry><type>uint32_t</type></entry>
305	    <entry>Number of X request in in this connection</entry>
306	  </row>
307	</tbody>
308      </tgroup>
309    </table>
310    </para>
311  </sect1>
312
313  <sect1 id="examples">
314    <title>Examples</title>
315
316    <example id="Counting_requests_by_request_name">
317      <title>Counting requests by request name</title>
318
319      <para>
320	This script simply increments a counter for each different request
321	made, and when you exit the script (such as by hitting
322	<keycombo action='simul'><keycap>Control</keycap><keycap>C</keycap>
323	</keycombo>) prints the counts.
324
325	<programlisting>
326#!/usr/sbin/dtrace -s
327
328Xserver*:::request-start
329{
330    @counts[copyinstr(arg0)] = count();
331}
332	</programlisting>
333
334	The output from a short run may appear as:
335	<screen>
336  QueryPointer                                                      1
337  CreatePixmap                                                      2
338  FreePixmap                                                        2
339  PutImage                                                          2
340  ChangeGC                                                         10
341  CopyArea                                                         10
342  CreateGC                                                         14
343  FreeGC                                                           14
344  RENDER                                                           28
345  SetClipRectangles                                                40
346	</screen>
347      </para>
348
349      <para>
350	This can be rewritten slightly to cache the string containing the name
351	of the request since it will be reused many times, instead of copying
352	it over and over from the kernel:
353
354	<programlisting>
355#!/usr/sbin/dtrace -s
356
357string Xrequest[uintptr_t];
358
359Xserver*:::request-start
360/Xrequest[arg0] == ""/
361{
362    Xrequest[arg0] = copyinstr(arg0);
363}
364
365Xserver*:::request-start
366{
367    @counts[Xrequest[arg0]] = count();
368}
369	</programlisting>
370      </para>
371    </example>
372
373    <example id="Get_average_CPU_time_per_request">
374      <title>Get average CPU time per request</title>
375
376      <para>This script records the CPU time used between the probes at
377	the start and end of each request and aggregates it per request type.
378
379	<programlisting>
380#!/usr/sbin/dtrace -s
381
382Xserver*:::request-start
383{
384    reqstart = vtimestamp;
385}
386
387Xserver*:::request-done
388{
389    @times[copyinstr(arg0)] = avg(vtimestamp - reqstart);
390}
391	</programlisting>
392
393	The output from a sample run might look like:
394
395	<screen>
396  ChangeGC                                                        889
397  MapWindow                                                       907
398  SetClipRectangles                                              1319
399  PolyPoint                                                      1413
400  PolySegment                                                    1434
401  PolyRectangle                                                  1828
402  FreeCursor                                                     1895
403  FreeGC                                                         1950
404  CreateGC                                                       2244
405  FreePixmap                                                     2246
406  GetInputFocus                                                  2249
407  TranslateCoords                                                8508
408  QueryTree                                                      8846
409  GetGeometry                                                    9948
410  CreatePixmap                                                  12111
411  AllowEvents                                                   14090
412  GrabServer                                                    14791
413  MIT-SCREEN-SAVER                                              16747
414  ConfigureWindow                                               22917
415  SetInputFocus                                                 28521
416  PutImage                                                     240841
417
418	</screen>
419      </para>
420    </example>
421
422    <example id="Monitoring_clients_that_connect_and_disconnect">
423      <title>Monitoring clients that connect and disconnect</title>
424
425      <para>
426	This script simply prints information about each client that
427	connects or disconnects from the server while it is running.
428	Since the provider is specified as <code>Xserver$1</code> instead
429	of <code>Xserver*</code> like previous examples, it won't monitor
430	all Xserver processes running on the machine, but instead expects
431	the process id of the X server to monitor to be specified as the
432	argument to the script.
433
434	<programlisting>
435#!/usr/sbin/dtrace -s
436
437Xserver$1:::client-connect
438{
439	printf("** Client Connect: id %d\n", arg0);
440}
441
442Xserver$1:::client-auth
443{
444	printf("** Client auth'ed: id %d =&gt; %s pid %d\n",
445		arg0, copyinstr(arg1), arg2);
446}
447
448Xserver$1:::client-disconnect
449{
450	printf("** Client Disconnect: id %d\n", arg0);
451}
452	</programlisting>
453
454	A sample run:
455
456	<screen>
457<prompt>#</prompt> <userinput>./foo.d 5790</userinput>
458<computeroutput>dtrace: script './foo.d' matched 4 probes
459CPU     ID                    FUNCTION:NAME
460  0  15774 CloseDownClient:client-disconnect ** Client Disconnect: id 65
461
462  2  15774 CloseDownClient:client-disconnect ** Client Disconnect: id 64
463
464  0  15773 EstablishNewConnections:client-connect ** Client Connect: id 64
465
466  0  15772            AuthAudit:client-auth ** Client auth'ed: id 64 =&gt; local host pid 2034
467
468  0  15773 EstablishNewConnections:client-connect ** Client Connect: id 65
469
470  0  15772            AuthAudit:client-auth ** Client auth'ed: id 65 =&gt; local host pid 2034
471
472  0  15774 CloseDownClient:client-disconnect ** Client Disconnect: id 64
473	  </computeroutput>
474	</screen>
475
476      </para>
477    </example>
478
479    <example id="Monitoring_clients_creating_Pixmaps">
480      <title>Monitoring clients creating Pixmaps</title>
481
482      <para>
483	This script can be used to determine which clients are creating
484	pixmaps in the X server, printing information about each client
485	as it connects to help trace it back to the program on the other
486	end of the X connection.
487
488	<programlisting>
489#!/usr/sbin/dtrace -qs
490
491string Xrequest[uintptr_t];
492string Xrestype[uintptr_t];
493
494Xserver$1:::request-start
495/Xrequest[arg0] == ""/
496{
497	Xrequest[arg0] = copyinstr(arg0);
498}
499
500Xserver$1:::resource-alloc
501/arg3 != 0 &amp;&amp; Xrestype[arg3] == ""/
502{
503	Xrestype[arg3] = copyinstr(arg3);
504}
505
506
507Xserver$1:::request-start
508/Xrequest[arg0] == "X_CreatePixmap"/
509{
510	printf("-&gt; %s: client %d\n", Xrequest[arg0], arg3);
511}
512
513Xserver$1:::request-done
514/Xrequest[arg0] == "X_CreatePixmap"/
515{
516	printf("&lt;- %s: client %d\n", Xrequest[arg0], arg3);
517}
518
519Xserver$1:::resource-alloc
520/Xrestype[arg3] == "PIXMAP"/
521{
522	printf("** Pixmap alloc: %08x\n", arg0);
523}
524
525
526Xserver$1:::resource-free
527/Xrestype[arg3] == "PIXMAP"/
528{
529	printf("** Pixmap free:  %08x\n", arg0);
530}
531
532Xserver$1:::client-connect
533{
534	printf("** Client Connect: id %d\n", arg0);
535}
536
537Xserver$1:::client-auth
538{
539	printf("** Client auth'ed: id %d =&gt; %s pid %d\n",
540		arg0, copyinstr(arg1), arg2);
541}
542
543Xserver$1:::client-disconnect
544{
545	printf("** Client Disconnect: id %d\n", arg0);
546}
547	</programlisting>
548
549	Sample output from a run of this script:
550	<screen><computeroutput>
551** Client Connect: id 17
552** Client auth'ed: id 17 =&gt; local host pid 20273
553-&gt; X_CreatePixmap: client 17
554** Pixmap alloc: 02200009
555&lt;- X_CreatePixmap: client 17
556-&gt; X_CreatePixmap: client 15
557** Pixmap alloc: 01e00180
558&lt;- X_CreatePixmap: client 15
559-&gt; X_CreatePixmap: client 15
560** Pixmap alloc: 01e00181
561&lt;- X_CreatePixmap: client 15
562-&gt; X_CreatePixmap: client 14
563** Pixmap alloc: 01c004c8
564&lt;- X_CreatePixmap: client 14
565** Pixmap free:  02200009
566** Client Disconnect: id 17
567** Pixmap free:  01e00180
568** Pixmap free:  01e00181
569	  </computeroutput></screen>
570
571      </para>
572
573    </example>
574
575
576  </sect1>
577
578</article>
579
580