Imported Upstream version 1.15.1
[deb_xorg-server.git] / doc / dtrace / Xserver-DTrace.xml
CommitLineData
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>
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. 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 &amp; 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 &lt;<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>&gt;
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 &lt;<ulink url="http://cgit.freedesktop.org/xorg/proto/xproto/tree/Xproto.h"><filename class="headerfile">X11/Xproto.h</filename></ulink>&gt;
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
410Xserver*:::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
439string Xrequest[uintptr_t];
440
441Xserver*:::request-start
442/Xrequest[arg0] == ""/
443{
444 Xrequest[arg0] = copyinstr(arg0);
445}
446
447Xserver*:::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
464Xserver*:::request-start
465{
466 reqstart = vtimestamp;
467}
468
469Xserver*:::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
519Xserver$1:::client-connect
520{
521 printf("** Client Connect: id %d\n", arg0);
522}
523
524Xserver$1:::client-auth
525{
526 printf("** Client auth'ed: id %d =&gt; %s pid %d\n",
527 arg0, copyinstr(arg1), arg2);
528}
529
530Xserver$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
541CPU 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 =&gt; 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 =&gt; 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
573string Xrequest[uintptr_t];
574string Xrestype[uintptr_t];
575
576Xserver$1:::request-start
577/Xrequest[arg0] == ""/
578{
579 Xrequest[arg0] = copyinstr(arg0);
580}
581
582Xserver$1:::resource-alloc
583/arg3 != 0 &amp;&amp; Xrestype[arg3] == ""/
584{
585 Xrestype[arg3] = copyinstr(arg3);
586}
587
588
589Xserver$1:::request-start
590/Xrequest[arg0] == "X_CreatePixmap"/
591{
592 printf("-&gt; %s: client %d\n", Xrequest[arg0], arg3);
593}
594
595Xserver$1:::request-done
596/Xrequest[arg0] == "X_CreatePixmap"/
597{
598 printf("&lt;- %s: client %d\n", Xrequest[arg0], arg3);
599}
600
601Xserver$1:::resource-alloc
602/Xrestype[arg3] == "PIXMAP"/
603{
604 printf("** Pixmap alloc: %08x\n", arg0);
605}
606
607
608Xserver$1:::resource-free
609/Xrestype[arg3] == "PIXMAP"/
610{
611 printf("** Pixmap free: %08x\n", arg0);
612}
613
614Xserver$1:::client-connect
615{
616 printf("** Client Connect: id %d\n", arg0);
617}
618
619Xserver$1:::client-auth
620{
621 printf("** Client auth'ed: id %d =&gt; %s pid %d\n",
622 arg0, copyinstr(arg1), arg2);
623}
624
625Xserver$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 =&gt; local host pid 20273
635-&gt; X_CreatePixmap: client 17
636** Pixmap alloc: 02200009
637&lt;- X_CreatePixmap: client 17
638-&gt; X_CreatePixmap: client 15
639** Pixmap alloc: 01e00180
640&lt;- X_CreatePixmap: client 15
641-&gt; X_CreatePixmap: client 15
642** Pixmap alloc: 01e00181
643&lt;- X_CreatePixmap: client 15
644-&gt; X_CreatePixmap: client 14
645** Pixmap alloc: 01c004c8
646&lt;- 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] &amp; (1 &lt;&lt; ((bit) &amp; 7)))
678
679 s += sprintf(s, "nval: %d ::", (int)THIS->nvaluators);
680 for (i = 0; i &lt; 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>
706Event: device 13 type 4 detail 1 flags 0x0 nval: 0 ::
707Event: device 13 type 6 detail 0 flags 0xa nval: 1 :: 0: 1
708Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -1
709Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -1
710Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 4 1: -3
711Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 3 1: -3
712Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 3 1: -2
713Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -2
714Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -2
715Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 2 1: -2
716Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 1: -1
717Event: device 13 type 6 detail 0 flags 0xa nval: 2 :: 0: 1: -1
718Event: 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>