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 & 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 <<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>> 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 <<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>> 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 => %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 => 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 => 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 && Xrestype[arg3] == ""/ 502{ 503 Xrestype[arg3] = copyinstr(arg3); 504} 505 506 507Xserver$1:::request-start 508/Xrequest[arg0] == "X_CreatePixmap"/ 509{ 510 printf("-> %s: client %d\n", Xrequest[arg0], arg3); 511} 512 513Xserver$1:::request-done 514/Xrequest[arg0] == "X_CreatePixmap"/ 515{ 516 printf("<- %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 => %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 => local host pid 20273 553-> X_CreatePixmap: client 17 554** Pixmap alloc: 02200009 555<- X_CreatePixmap: client 17 556-> X_CreatePixmap: client 15 557** Pixmap alloc: 01e00180 558<- X_CreatePixmap: client 15 559-> X_CreatePixmap: client 15 560** Pixmap alloc: 01e00181 561<- X_CreatePixmap: client 15 562-> X_CreatePixmap: client 14 563** Pixmap alloc: 01c004c8 564<- 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