]> granicus.if.org Git - strace/blob - time.c
3d2f6c99c7b684889e596d3af72e8e809896738d
[strace] / time.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *      $Id$
30  */
31
32 #include "defs.h"
33
34 #ifdef LINUX
35 #include <linux/version.h>
36 #include <sys/timex.h>
37 #include <linux/ioctl.h>
38 #include <linux/rtc.h>
39 #endif /* LINUX */
40
41 struct timeval32
42 {
43         u_int32_t tv_sec, tv_usec;
44 };
45
46 static void
47 tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv)
48 {
49         tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec);
50 }
51
52 static void
53 tprint_timeval(struct tcb *tcp, const struct timeval *tv)
54 {
55         tprintf("{%lu, %lu}",
56                 (unsigned long) tv->tv_sec, (unsigned long) tv->tv_usec);
57 }
58
59 void
60 printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness)
61 {
62         if (addr == 0)
63                 tprintf("NULL");
64         else if (!verbose(tcp))
65                 tprintf("%#lx", addr);
66         else
67         {
68                 int     rc;
69
70                 if (bitness == BITNESS_32
71 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
72                     || personality_wordsize[current_personality] == 4
73 #endif
74                         )
75                 {
76                         struct timeval32 tv;
77
78                         if ((rc = umove(tcp, addr, &tv)) >= 0)
79                                 tprint_timeval32(tcp, &tv);
80                 } else
81                 {
82                         struct timeval tv;
83
84                         if ((rc = umove(tcp, addr, &tv)) >= 0)
85                                 tprint_timeval(tcp, &tv);
86                 }
87
88                 if (rc < 0)
89                         tprintf("{...}");
90         }
91 }
92
93 void
94 sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
95 {
96         if (addr == 0)
97                 strcpy(buf, "NULL");
98         else if (!verbose(tcp))
99                 sprintf(buf, "%#lx", addr);
100         else
101         {
102                 int     rc;
103
104                 if (bitness == BITNESS_32
105 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
106                     || personality_wordsize[current_personality] == 4
107 #endif
108                         )
109                 {
110                         struct timeval32 tv;
111
112                         if ((rc = umove(tcp, addr, &tv)) >= 0)
113                                 sprintf(buf, "{%u, %u}",
114                                         tv.tv_sec, tv.tv_usec);
115                 } else
116                 {
117                         struct timeval tv;
118
119                         if ((rc = umove(tcp, addr, &tv)) >= 0)
120                                 sprintf(buf, "{%lu, %lu}",
121                                         (unsigned long) tv.tv_sec,
122                                         (unsigned long) tv.tv_usec);
123                 }
124
125                 if (rc < 0)
126                         strcpy(buf, "{...}");
127         }
128 }
129
130 int
131 sys_time(tcp)
132 struct tcb *tcp;
133 {
134         if (exiting(tcp)) {
135 #ifndef SVR4
136                 printnum(tcp, tcp->u_arg[0], "%ld");
137 #endif /* SVR4 */
138         }
139         return 0;
140 }
141
142 int
143 sys_stime(tcp)
144 struct tcb *tcp;
145 {
146         if (exiting(tcp)) {
147                 printnum(tcp, tcp->u_arg[0], "%ld");
148         }
149         return 0;
150 }
151
152 int
153 sys_gettimeofday(tcp)
154 struct tcb *tcp;
155 {
156         if (exiting(tcp)) {
157                 if (syserror(tcp)) {
158                         tprintf("%#lx, %#lx",
159                                 tcp->u_arg[0], tcp->u_arg[1]);
160                         return 0;
161                 }
162                 printtv(tcp, tcp->u_arg[0]);
163 #ifndef SVR4
164                 tprintf(", ");
165                 printtv(tcp, tcp->u_arg[1]);
166 #endif /* !SVR4 */
167         }
168         return 0;
169 }
170
171
172 #ifdef ALPHA
173 int
174 sys_osf_gettimeofday(tcp)
175 struct tcb *tcp;
176 {
177     if (exiting(tcp)) {
178         if (syserror(tcp)) {
179             tprintf("%#lx, %#lx",
180                     tcp->u_arg[0], tcp->u_arg[1]);
181             return 0;
182         }
183         printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32);
184 #ifndef SVR4
185         tprintf(", ");
186         printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
187 #endif /* !SVR4 */
188     }
189     return 0;
190 }
191 #endif
192
193 int
194 sys_settimeofday(tcp)
195 struct tcb *tcp;
196 {
197         if (entering(tcp)) {
198                 printtv(tcp, tcp->u_arg[0]);
199 #ifndef SVR4
200                 tprintf(", ");
201                 printtv(tcp, tcp->u_arg[1]);
202 #endif /* !SVR4 */
203         }
204         return 0;
205 }
206
207 #ifdef ALPHA
208 int
209 sys_osf_settimeofday(tcp)
210 struct tcb *tcp;
211 {
212     if (entering(tcp)) {
213         printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32);
214 #ifndef SVR4
215         tprintf(", ");
216         printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
217 #endif /* !SVR4 */
218     }
219     return 0;
220 }
221 #endif
222
223 int
224 sys_adjtime(tcp)
225 struct tcb *tcp;
226 {
227         if (entering(tcp)) {
228                 printtv(tcp, tcp->u_arg[0]);
229                 tprintf(", ");
230         } else {
231                 if (syserror(tcp))
232                         tprintf("%#lx", tcp->u_arg[1]);
233                 else
234                         printtv(tcp, tcp->u_arg[1]);
235         }
236         return 0;
237 }
238
239 static const struct xlat which[] = {
240         { ITIMER_REAL,  "ITIMER_REAL"   },
241         { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"},
242         { ITIMER_PROF,  "ITIMER_PROF"   },
243         { 0,            NULL            },
244 };
245
246 static void
247 printitv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness)
248 {
249         if (addr == 0)
250                 tprintf("NULL");
251         else if (!verbose(tcp))
252                 tprintf("%#lx", addr);
253         else
254         {
255                 int     rc;
256
257                 if (bitness == BITNESS_32
258 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
259                     || personality_wordsize[current_personality] == 4
260 #endif
261                         )
262                 {
263                         struct
264                         {
265                                 struct timeval32 it_interval, it_value;
266                         } itv;
267
268                         if ((rc = umove(tcp, addr, &itv)) >= 0)
269                                 tprintf("{it_interval=");
270                                 tprint_timeval32(tcp, &itv.it_interval);
271                                 tprintf(", it_value=");
272                                 tprint_timeval32(tcp, &itv.it_value);
273                                 tprintf("}");
274                 } else
275                 {
276                         struct itimerval itv;
277
278                         if ((rc = umove(tcp, addr, &itv)) >= 0)
279                                 tprintf("{it_interval=");
280                                 tprint_timeval(tcp, &itv.it_interval);
281                                 tprintf(", it_value=");
282                                 tprint_timeval(tcp, &itv.it_value);
283                                 tprintf("}");
284                 }
285
286                 if (rc < 0)
287                         tprintf("{...}");
288         }
289 }
290
291 #define printitv(tcp, addr)     \
292         printitv_bitness((tcp), (addr), BITNESS_CURRENT)
293
294 int
295 sys_getitimer(tcp)
296 struct tcb *tcp;
297 {
298         if (entering(tcp)) {
299                 printxval(which, tcp->u_arg[0], "ITIMER_???");
300                 tprintf(", ");
301         } else {
302                 if (syserror(tcp))
303                         tprintf("%#lx", tcp->u_arg[1]);
304                 else
305                         printitv(tcp, tcp->u_arg[1]);
306         }
307         return 0;
308 }
309
310
311 #ifdef ALPHA
312 int
313 sys_osf_getitimer(tcp)
314 struct tcb *tcp;
315 {
316     if (entering(tcp)) {
317         printxval(which, tcp->u_arg[0], "ITIMER_???");
318         tprintf(", ");
319     } else {
320         if (syserror(tcp))
321             tprintf("%#lx", tcp->u_arg[1]);
322         else
323             printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
324     }
325     return 0;
326 }
327 #endif
328
329 int
330 sys_setitimer(tcp)
331 struct tcb *tcp;
332 {
333         if (entering(tcp)) {
334                 printxval(which, tcp->u_arg[0], "ITIMER_???");
335                 tprintf(", ");
336                 printitv(tcp, tcp->u_arg[1]);
337                 tprintf(", ");
338         } else {
339                 if (syserror(tcp))
340                         tprintf("%#lx", tcp->u_arg[2]);
341                 else
342                         printitv(tcp, tcp->u_arg[2]);
343         }
344         return 0;
345 }
346
347 #ifdef ALPHA
348 int
349 sys_osf_setitimer(tcp)
350 struct tcb *tcp;
351 {
352     if (entering(tcp)) {
353         printxval(which, tcp->u_arg[0], "ITIMER_???");
354         tprintf(", ");
355         printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
356         tprintf(", ");
357     } else {
358         if (syserror(tcp))
359             tprintf("%#lx", tcp->u_arg[2]);
360         else
361             printitv_bitness(tcp, tcp->u_arg[2], BITNESS_32);
362     }
363     return 0;
364 }
365 #endif
366
367 #ifdef LINUX
368
369 static const struct xlat adjtimex_modes[] = {
370   { 0, "0" },
371 #ifdef ADJ_OFFSET
372   { ADJ_OFFSET, "ADJ_OFFSET" },
373 #endif
374 #ifdef ADJ_FREQUENCY
375   { ADJ_FREQUENCY, "ADJ_FREQUENCY" },
376 #endif
377 #ifdef ADJ_MAXERROR
378   { ADJ_MAXERROR, "ADJ_MAXERROR" },
379 #endif
380 #ifdef ADJ_ESTERROR
381   { ADJ_ESTERROR, "ADJ_ESTERROR" },
382 #endif
383 #ifdef ADJ_STATUS
384   { ADJ_STATUS, "ADJ_STATUS" },
385 #endif
386 #ifdef ADJ_TIMECONST
387   { ADJ_TIMECONST, "ADJ_TIMECONST" },
388 #endif
389 #ifdef ADJ_TICK
390   { ADJ_TICK, "ADJ_TICK" },
391 #endif
392 #ifdef ADJ_OFFSET_SINGLESHOT
393   { ADJ_OFFSET_SINGLESHOT, "ADJ_OFFSET_SINGLESHOT" },
394 #endif
395   { 0,             NULL }
396 };
397
398 static const struct xlat adjtimex_status[] = {
399 #ifdef STA_PLL
400   { STA_PLL, "STA_PLL" },
401 #endif
402 #ifdef STA_PPSFREQ
403   { STA_PPSFREQ, "STA_PPSFREQ" },
404 #endif
405 #ifdef STA_PPSTIME
406   { STA_PPSTIME, "STA_PPSTIME" },
407 #endif
408 #ifdef STA_FLL
409   { STA_FLL, "STA_FLL" },
410 #endif
411 #ifdef STA_INS
412   { STA_INS, "STA_INS" },
413 #endif
414 #ifdef STA_DEL
415   { STA_DEL, "STA_DEL" },
416 #endif
417 #ifdef STA_UNSYNC
418   { STA_UNSYNC, "STA_UNSYNC" },
419 #endif
420 #ifdef STA_FREQHOLD
421   { STA_FREQHOLD, "STA_FREQHOLD" },
422 #endif
423 #ifdef STA_PPSSIGNAL
424   { STA_PPSSIGNAL, "STA_PPSSIGNAL" },
425 #endif
426 #ifdef STA_PPSJITTER
427   { STA_PPSJITTER, "STA_PPSJITTER" },
428 #endif
429 #ifdef STA_PPSWANDER
430   { STA_PPSWANDER, "STA_PPSWANDER" },
431 #endif
432 #ifdef STA_PPSERROR
433   { STA_PPSERROR, "STA_PPSERROR" },
434 #endif
435 #ifdef STA_CLOCKERR
436   { STA_CLOCKERR, "STA_CLOCKERR" },
437 #endif
438   { 0,             NULL }
439 };
440
441 static const struct xlat adjtimex_state[] = {
442 #ifdef TIME_OK
443   { TIME_OK, "TIME_OK" },
444 #endif
445 #ifdef TIME_INS
446   { TIME_INS, "TIME_INS" },
447 #endif
448 #ifdef TIME_DEL
449   { TIME_DEL, "TIME_DEL" },
450 #endif
451 #ifdef TIME_OOP
452   { TIME_OOP, "TIME_OOP" },
453 #endif
454 #ifdef TIME_WAIT
455   { TIME_WAIT, "TIME_WAIT" },
456 #endif
457 #ifdef TIME_ERROR
458   { TIME_ERROR, "TIME_ERROR" },
459 #endif
460   { 0,             NULL }
461 };
462
463 #if SUPPORTED_PERSONALITIES > 1
464 static int
465 tprint_timex32(struct tcb *tcp, long addr)
466 {
467         struct
468         {
469                 unsigned int modes;
470                 int     offset;
471                 int     freq;
472                 int     maxerror;
473                 int     esterror;
474                 int     status;
475                 int     constant;
476                 int     precision;
477                 int     tolerance;
478                 struct timeval32 time;
479                 int     tick;
480                 int     ppsfreq;
481                 int     jitter;
482                 int     shift;
483                 int     stabil;
484                 int     jitcnt;
485                 int     calcnt;
486                 int     errcnt;
487                 int     stbcnt;
488         } tx;
489
490         if (umove(tcp, addr, &tx) < 0)
491                 return -1;
492
493         tprintf("{modes=");
494         printflags(adjtimex_modes, tx.modes, "ADJ_???");
495         tprintf(", offset=%d, freq=%d, maxerror=%d, ",
496                 tx.offset, tx.freq, tx.maxerror);
497         tprintf("esterror=%u, status=", tx.esterror);
498         printflags(adjtimex_status, tx.status, "STA_???");
499         tprintf(", constant=%d, precision=%u, ",
500                 tx.constant, tx.precision);
501         tprintf("tolerance=%d, time=", tx.tolerance);
502         tprint_timeval32(tcp, &tx.time);
503         tprintf(", tick=%d, ppsfreq=%d, jitter=%d",
504                 tx.tick, tx.ppsfreq, tx.jitter);
505         tprintf(", shift=%d, stabil=%d, jitcnt=%d",
506                 tx.shift, tx.stabil, tx.jitcnt);
507         tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d",
508                 tx.calcnt, tx.errcnt, tx.stbcnt);
509         tprintf("}");
510         return 0;
511 }
512 #endif /* SUPPORTED_PERSONALITIES > 1 */
513
514 static int
515 tprint_timex(struct tcb *tcp, long addr)
516 {
517         struct timex tx;
518
519 #if SUPPORTED_PERSONALITIES > 1
520         if (personality_wordsize[current_personality] == 4)
521                 return tprint_timex32(tcp, addr);
522 #endif
523         if (umove(tcp, addr, &tx) < 0)
524                 return -1;
525
526 #if LINUX_VERSION_CODE < 66332
527         tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
528                 tx.mode, tx.offset, tx.frequency);
529         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
530                 tx.maxerror, tx.esterror, tx.status);
531         tprintf("time_constant=%ld, precision=%lu, ",
532                 tx.time_constant, tx.precision);
533         tprintf("tolerance=%ld, time=", tx.tolerance);
534         tprint_timeval(tcp, &tx.time);
535 #else
536         tprintf("{modes=");
537         printflags(adjtimex_modes, tx.modes, "ADJ_???");
538         tprintf(", offset=%ld, freq=%ld, maxerror=%ld, ",
539                 tx.offset, tx.freq, tx.maxerror);
540         tprintf("esterror=%lu, status=", tx.esterror);
541         printflags(adjtimex_status, tx.status, "STA_???");
542         tprintf(", constant=%ld, precision=%lu, ",
543                 tx.constant, tx.precision);
544         tprintf("tolerance=%ld, time=", tx.tolerance);
545         tprint_timeval(tcp, &tx.time);
546         tprintf(", tick=%ld, ppsfreq=%ld, jitter=%ld",
547                 tx.tick, tx.ppsfreq, tx.jitter);
548         tprintf(", shift=%d, stabil=%ld, jitcnt=%ld",
549                 tx.shift, tx.stabil, tx.jitcnt);
550         tprintf(", calcnt=%ld, errcnt=%ld, stbcnt=%ld",
551                 tx.calcnt, tx.errcnt, tx.stbcnt);
552 #endif
553         tprintf("}");
554         return 0;
555 }
556
557 int
558 sys_adjtimex(struct tcb *tcp)
559 {
560         if (exiting(tcp)) {
561                 if (tcp->u_arg[0] == 0)
562                         tprintf("NULL");
563                 else if (syserror(tcp) || !verbose(tcp))
564                         tprintf("%#lx", tcp->u_arg[0]);
565                 else if (tprint_timex(tcp, tcp->u_arg[0]) < 0)
566                         tprintf("{...}");
567                 tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval);
568                 if (tcp->auxstr)
569                         return RVAL_STR;
570         }
571         return 0;
572 }
573
574 static const struct xlat clockflags[] = {
575   { TIMER_ABSTIME, "TIMER_ABSTIME" },
576   { 0,             NULL }
577 };
578
579 static const struct xlat clocknames[] = {
580 #ifdef CLOCK_REALTIME
581   { CLOCK_REALTIME, "CLOCK_REALTIME" },
582 #endif
583 #ifdef CLOCK_MONOTONIC
584   { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" },
585 #endif
586   { 0,             NULL }
587 };
588
589 int
590 sys_clock_settime(tcp)
591 struct tcb *tcp;
592 {
593         if (entering(tcp)) {
594                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
595                 tprintf(", ");
596                 printtv(tcp, tcp->u_arg[1]);
597         }
598         return 0;
599 }
600
601 int
602 sys_clock_gettime(tcp)
603 struct tcb *tcp;
604 {
605         if (entering(tcp)) {
606                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
607                 tprintf(", ");
608         } else {
609                 if (syserror(tcp))
610                         tprintf("%#lx", tcp->u_arg[1]);
611                 else
612                         printtv(tcp, tcp->u_arg[1]);
613         }
614         return 0;
615 }
616
617 int
618 sys_clock_nanosleep(tcp)
619 struct tcb *tcp;
620 {
621         if (entering(tcp)) {
622                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
623                 tprintf(", ");
624                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
625                 tprintf(", ");
626                 printtv(tcp, tcp->u_arg[2]);
627                 tprintf(", ");
628         } else {
629                 if (syserror(tcp))
630                         tprintf("%#lx", tcp->u_arg[3]);
631                 else
632                         printtv(tcp, tcp->u_arg[3]);
633         }
634         return 0;
635 }
636
637 #ifndef SIGEV_THREAD_ID
638 # define SIGEV_THREAD_ID 4
639 #endif
640 static const struct xlat sigev_value[] = {
641         { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
642         { SIGEV_NONE+1, "SIGEV_NONE" },
643         { SIGEV_THREAD+1, "SIGEV_THREAD" },
644         { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
645         { 0, NULL }
646 };
647
648 #if SUPPORTED_PERSONALITIES > 1
649 static void
650 printsigevent32(struct tcb *tcp, long arg)
651 {
652         struct
653         {
654                 int     sigev_value;
655                 int     sigev_signo;
656                 int     sigev_notify;
657
658                 union
659                 {
660                         int     tid;
661                         struct
662                         {
663                                 int     function, attribute;
664                         } thread;
665                 } un;
666         } sev;
667
668         if (umove(tcp, arg, &sev) < 0)
669                 tprintf("{...}");
670         else
671         {
672                 tprintf("{%#x, ", sev.sigev_value);
673                 if (sev.sigev_notify == SIGEV_SIGNAL)
674                         tprintf("%s, ", signame(sev.sigev_signo));
675                 else
676                         tprintf("%u, ", sev.sigev_signo);
677                 printxval(sigev_value, sev.sigev_notify + 1, "SIGEV_???");
678                 tprintf(", ");
679                 if (sev.sigev_notify == SIGEV_THREAD_ID)
680                         tprintf("{%d}", sev.un.tid);
681                 else if (sev.sigev_notify == SIGEV_THREAD)
682                         tprintf("{%#x, %#x}",
683                                 sev.un.thread.function,
684                                 sev.un.thread.attribute);
685                 else
686                         tprintf("{...}");
687                 tprintf("}");
688         }
689 }
690 #endif
691
692 void
693 printsigevent(struct tcb *tcp, long arg)
694 {
695         struct sigevent sev;
696
697 #if SUPPORTED_PERSONALITIES > 1
698         if (personality_wordsize[current_personality] == 4)
699         {
700                 printsigevent32(tcp, arg);
701                 return;
702         }
703 #endif
704         if (umove (tcp, arg, &sev) < 0)
705                 tprintf("{...}");
706         else {
707                 tprintf("{%p, ", sev.sigev_value.sival_ptr);
708                 if (sev.sigev_notify == SIGEV_SIGNAL)
709                         tprintf("%s, ", signame(sev.sigev_signo));
710                 else
711                         tprintf("%u, ", sev.sigev_signo);
712                 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
713                 tprintf(", ");
714                 if (sev.sigev_notify == SIGEV_THREAD_ID)
715                         /* _pad[0] is the _tid field which might not be
716                            present in the userlevel definition of the
717                            struct.  */
718                         tprintf("{%d}", sev._sigev_un._pad[0]);
719                 else if (sev.sigev_notify == SIGEV_THREAD)
720                         tprintf("{%p, %p}", sev.sigev_notify_function,
721                                 sev.sigev_notify_attributes);
722                 else
723                         tprintf("{...}");
724                 tprintf("}");
725         }
726 }
727
728 int
729 sys_timer_create(tcp)
730 struct tcb *tcp;
731 {
732         if (entering(tcp)) {
733                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
734                 tprintf(", ");
735                 printsigevent(tcp, tcp->u_arg[1]);
736                 tprintf(", ");
737         } else {
738                 void *p;
739
740                 if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &p) < 0)
741                         tprintf("%#lx", tcp->u_arg[2]);
742                 else
743                         tprintf("{%p}", p);
744         }
745         return 0;
746 }
747
748 int
749 sys_timer_settime(tcp)
750 struct tcb *tcp;
751 {
752         if (entering(tcp)) {
753                 tprintf("%#lx, ", tcp->u_arg[0]);
754                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
755                 tprintf(", ");
756                 printitv(tcp, tcp->u_arg[2]);
757                 tprintf(", ");
758         } else {
759                 if (syserror(tcp))
760                         tprintf("%#lx", tcp->u_arg[3]);
761                 else
762                         printitv(tcp, tcp->u_arg[3]);
763         }
764         return 0;
765 }
766
767 int
768 sys_timer_gettime(tcp)
769 struct tcb *tcp;
770 {
771         if (entering(tcp)) {
772                 tprintf("%#lx, ", tcp->u_arg[0]);
773         } else {
774                 if (syserror(tcp))
775                         tprintf("%#lx", tcp->u_arg[1]);
776                 else
777                         printitv(tcp, tcp->u_arg[1]);
778         }
779         return 0;
780 }
781
782 static void
783 print_rtc(tcp, rt)
784 struct tcb *tcp;
785 const struct rtc_time *rt;
786 {
787         tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
788                 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
789                 rt->tm_sec, rt->tm_min, rt->tm_hour,
790                 rt->tm_mday, rt->tm_mon, rt->tm_year);
791         if (!abbrev(tcp))
792                 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
793                         rt->tm_wday, rt->tm_yday, rt->tm_isdst);
794         else
795                 tprintf("...}");
796 }
797
798 int
799 rtc_ioctl(tcp, code, arg)
800 struct tcb *tcp;
801 long code;
802 long arg;
803 {
804         switch (code) {
805         case RTC_ALM_SET:
806         case RTC_SET_TIME:
807                 if (entering(tcp)) {
808                         struct rtc_time rt;
809                         if (umove(tcp, arg, &rt) < 0)
810                                 tprintf(", %#lx", arg);
811                         else {
812                                 tprintf(", ");
813                                 print_rtc(tcp, &rt);
814                         }
815                 }
816                 break;
817         case RTC_ALM_READ:
818         case RTC_RD_TIME:
819                 if (exiting(tcp)) {
820                         struct rtc_time rt;
821                         if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
822                                 tprintf(", %#lx", arg);
823                         else {
824                                 tprintf(", ");
825                                 print_rtc(tcp, &rt);
826                         }
827                 }
828                 break;
829         case RTC_IRQP_SET:
830         case RTC_EPOCH_SET:
831                 if (entering(tcp))
832                         tprintf(", %lu", arg);
833                 break;
834         case RTC_IRQP_READ:
835         case RTC_EPOCH_READ:
836                 if (exiting(tcp))
837                         tprintf(", %lu", arg);
838                 break;
839         case RTC_WKALM_SET:
840                 if (entering(tcp)) {
841                         struct rtc_wkalrm wk;
842                         if (umove(tcp, arg, &wk) < 0)
843                                 tprintf(", %#lx", arg);
844                         else {
845                                 tprintf(", {enabled=%d, pending=%d, ",
846                                         wk.enabled, wk.pending);
847                                 print_rtc(tcp, &wk.time);
848                                 tprintf("}");
849                         }
850                 }
851                 break;
852         case RTC_WKALM_RD:
853                 if (exiting(tcp)) {
854                         struct rtc_wkalrm wk;
855                         if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
856                                 tprintf(", %#lx", arg);
857                         else {
858                                 tprintf(", {enabled=%d, pending=%d, ",
859                                         wk.enabled, wk.pending);
860                                 print_rtc(tcp, &wk.time);
861                                 tprintf("}");
862                         }
863                 }
864                 break;
865         default:
866                 if (entering(tcp))
867                         tprintf(", %#lx", arg);
868                 break;
869         }
870         return 1;
871 }
872 #endif /* LINUX */