]> granicus.if.org Git - strace/blob - time.c
257d04b2ca09ee72d162ea552575bae1dbcf9c78
[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
40 #ifndef UTIME_NOW
41 #define UTIME_NOW ((1l << 30) - 1l)
42 #endif
43 #ifndef UTIME_OMIT
44 #define UTIME_OMIT ((1l << 30) - 2l)
45 #endif
46 #endif /* LINUX */
47
48 struct timeval32
49 {
50         u_int32_t tv_sec, tv_usec;
51 };
52
53 static void
54 tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv)
55 {
56         tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec);
57 }
58
59 static void
60 tprint_timeval(struct tcb *tcp, const struct timeval *tv)
61 {
62         tprintf("{%lu, %lu}",
63                 (unsigned long) tv->tv_sec, (unsigned long) tv->tv_usec);
64 }
65
66 void
67 printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness, int special)
68 {
69         if (addr == 0)
70                 tprintf("NULL");
71         else if (!verbose(tcp))
72                 tprintf("%#lx", addr);
73         else {
74                 int rc;
75
76                 if (bitness == BITNESS_32
77 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
78                     || personality_wordsize[current_personality] == 4
79 #endif
80                         )
81                 {
82                         struct timeval32 tv;
83
84                         if ((rc = umove(tcp, addr, &tv)) >= 0) {
85                                 if (special && tv.tv_sec == 0 &&
86                                     tv.tv_usec == UTIME_NOW)
87                                         tprintf("UTIME_NOW");
88                                 else if (special && tv.tv_sec == 0 &&
89                                          tv.tv_usec == UTIME_OMIT)
90                                         tprintf("UTIME_OMIT");
91                                 else
92                                         tprint_timeval32(tcp, &tv);
93                         }
94                 } else {
95                         struct timeval tv;
96
97                         if ((rc = umove(tcp, addr, &tv)) >= 0) {
98                                 if (special && tv.tv_sec == 0 &&
99                                     tv.tv_usec == UTIME_NOW)
100                                         tprintf("UTIME_NOW");
101                                 else if (special && tv.tv_sec == 0 &&
102                                          tv.tv_usec == UTIME_OMIT)
103                                         tprintf("UTIME_OMIT");
104                                 else
105                                         tprint_timeval(tcp, &tv);
106                         }
107                 }
108                 if (rc < 0)
109                         tprintf("{...}");
110         }
111 }
112
113 void
114 sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
115 {
116         if (addr == 0)
117                 strcpy(buf, "NULL");
118         else if (!verbose(tcp))
119                 sprintf(buf, "%#lx", addr);
120         else {
121                 int rc;
122
123                 if (bitness == BITNESS_32
124 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
125                     || personality_wordsize[current_personality] == 4
126 #endif
127                         )
128                 {
129                         struct timeval32 tv;
130
131                         if ((rc = umove(tcp, addr, &tv)) >= 0)
132                                 sprintf(buf, "{%u, %u}",
133                                         tv.tv_sec, tv.tv_usec);
134                 } else {
135                         struct timeval tv;
136
137                         if ((rc = umove(tcp, addr, &tv)) >= 0)
138                                 sprintf(buf, "{%lu, %lu}",
139                                         (unsigned long) tv.tv_sec,
140                                         (unsigned long) tv.tv_usec);
141                 }
142                 if (rc < 0)
143                         strcpy(buf, "{...}");
144         }
145 }
146
147 void print_timespec(struct tcb *tcp, long addr)
148 {
149         if (addr == 0)
150                 tprintf("NULL");
151         else if (!verbose(tcp))
152                 tprintf("%#lx", addr);
153         else {
154                 int rc;
155
156 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
157                 if (personality_wordsize[current_personality] == 4) {
158                         struct timeval32 tv;
159
160                         if ((rc = umove(tcp, addr, &tv)) >= 0)
161                                 tprintf("{%u, %u}",
162                                         tv.tv_sec, tv.tv_usec);
163                 } else
164 #endif
165                 {
166                         struct timespec ts;
167
168                         if ((rc = umove(tcp, addr, &ts)) >= 0)
169                                 tprintf("{%lu, %lu}",
170                                         (unsigned long) ts.tv_sec,
171                                         (unsigned long) ts.tv_nsec);
172                 }
173                 if (rc < 0)
174                         tprintf("{...}");
175         }
176 }
177
178 void sprint_timespec(char *buf, struct tcb *tcp, long addr)
179 {
180         if (addr == 0)
181                 strcpy(buf, "NULL");
182         else if (!verbose(tcp))
183                 sprintf(buf, "%#lx", addr);
184         else {
185                 int rc;
186
187 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
188                 if (personality_wordsize[current_personality] == 4) {
189                         struct timeval32 tv;
190
191                         if ((rc = umove(tcp, addr, &tv)) >= 0)
192                                 sprintf(buf, "{%u, %u}",
193                                         tv.tv_sec, tv.tv_usec);
194                 } else
195 #endif
196                 {
197                         struct timespec ts;
198
199                         if ((rc = umove(tcp, addr, &ts)) >= 0)
200                                 sprintf(buf, "{%lu, %lu}",
201                                         (unsigned long) ts.tv_sec,
202                                         (unsigned long) ts.tv_nsec);
203                 }
204                 if (rc < 0)
205                         strcpy(buf, "{...}");
206         }
207 }
208
209 int
210 sys_time(struct tcb *tcp)
211 {
212         if (exiting(tcp)) {
213 #ifndef SVR4
214                 printnum(tcp, tcp->u_arg[0], "%ld");
215 #endif /* SVR4 */
216         }
217         return 0;
218 }
219
220 int
221 sys_stime(struct tcb *tcp)
222 {
223         if (exiting(tcp)) {
224                 printnum(tcp, tcp->u_arg[0], "%ld");
225         }
226         return 0;
227 }
228
229 int
230 sys_gettimeofday(struct tcb *tcp)
231 {
232         if (exiting(tcp)) {
233                 if (syserror(tcp)) {
234                         tprintf("%#lx, %#lx",
235                                 tcp->u_arg[0], tcp->u_arg[1]);
236                         return 0;
237                 }
238                 printtv(tcp, tcp->u_arg[0]);
239 #ifndef SVR4
240                 tprintf(", ");
241                 printtv(tcp, tcp->u_arg[1]);
242 #endif /* !SVR4 */
243         }
244         return 0;
245 }
246
247
248 #ifdef ALPHA
249 int
250 sys_osf_gettimeofday(struct tcb *tcp)
251 {
252         if (exiting(tcp)) {
253                 if (syserror(tcp)) {
254                         tprintf("%#lx, %#lx", tcp->u_arg[0], tcp->u_arg[1]);
255                         return 0;
256                 }
257                 printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
258 #ifndef SVR4
259                 tprintf(", ");
260                 printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
261 #endif /* !SVR4 */
262         }
263         return 0;
264 }
265 #endif
266
267 int
268 sys_settimeofday(struct tcb *tcp)
269 {
270         if (entering(tcp)) {
271                 printtv(tcp, tcp->u_arg[0]);
272 #ifndef SVR4
273                 tprintf(", ");
274                 printtv(tcp, tcp->u_arg[1]);
275 #endif /* !SVR4 */
276         }
277         return 0;
278 }
279
280 #ifdef ALPHA
281 int
282 sys_osf_settimeofday(struct tcb *tcp)
283 {
284         if (entering(tcp)) {
285                 printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
286 #ifndef SVR4
287                 tprintf(", ");
288                 printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
289 #endif /* !SVR4 */
290         }
291         return 0;
292 }
293 #endif
294
295 int
296 sys_adjtime(struct tcb *tcp)
297 {
298         if (entering(tcp)) {
299                 printtv(tcp, tcp->u_arg[0]);
300                 tprintf(", ");
301         } else {
302                 if (syserror(tcp))
303                         tprintf("%#lx", tcp->u_arg[1]);
304                 else
305                         printtv(tcp, tcp->u_arg[1]);
306         }
307         return 0;
308 }
309
310 int
311 sys_nanosleep(struct tcb *tcp)
312 {
313         if (entering(tcp)) {
314                 print_timespec(tcp, tcp->u_arg[0]);
315                 tprintf(", ");
316         } else {
317                 if (!tcp->u_arg[1] || is_restart_error(tcp))
318                         print_timespec(tcp, tcp->u_arg[1]);
319                 else
320                         tprintf("%#lx", tcp->u_arg[1]);
321         }
322         return 0;
323 }
324
325 static const struct xlat which[] = {
326         { ITIMER_REAL,  "ITIMER_REAL"   },
327         { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"},
328         { ITIMER_PROF,  "ITIMER_PROF"   },
329         { 0,            NULL            },
330 };
331
332 static void
333 printitv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness)
334 {
335         if (addr == 0)
336                 tprintf("NULL");
337         else if (!verbose(tcp))
338                 tprintf("%#lx", addr);
339         else {
340                 int rc;
341
342                 if (bitness == BITNESS_32
343 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
344                     || personality_wordsize[current_personality] == 4
345 #endif
346                         )
347                 {
348                         struct {
349                                 struct timeval32 it_interval, it_value;
350                         } itv;
351
352                         if ((rc = umove(tcp, addr, &itv)) >= 0) {
353                                 tprintf("{it_interval=");
354                                 tprint_timeval32(tcp, &itv.it_interval);
355                                 tprintf(", it_value=");
356                                 tprint_timeval32(tcp, &itv.it_value);
357                                 tprintf("}");
358                         }
359                 } else {
360                         struct itimerval itv;
361
362                         if ((rc = umove(tcp, addr, &itv)) >= 0) {
363                                 tprintf("{it_interval=");
364                                 tprint_timeval(tcp, &itv.it_interval);
365                                 tprintf(", it_value=");
366                                 tprint_timeval(tcp, &itv.it_value);
367                                 tprintf("}");
368                         }
369                 }
370                 if (rc < 0)
371                         tprintf("{...}");
372         }
373 }
374
375 #define printitv(tcp, addr)     \
376         printitv_bitness((tcp), (addr), BITNESS_CURRENT)
377
378 int
379 sys_getitimer(struct tcb *tcp)
380 {
381         if (entering(tcp)) {
382                 printxval(which, tcp->u_arg[0], "ITIMER_???");
383                 tprintf(", ");
384         } else {
385                 if (syserror(tcp))
386                         tprintf("%#lx", tcp->u_arg[1]);
387                 else
388                         printitv(tcp, tcp->u_arg[1]);
389         }
390         return 0;
391 }
392
393
394 #ifdef ALPHA
395 int
396 sys_osf_getitimer(struct tcb *tcp)
397 {
398         if (entering(tcp)) {
399                 printxval(which, tcp->u_arg[0], "ITIMER_???");
400                 tprintf(", ");
401         } else {
402                 if (syserror(tcp))
403                         tprintf("%#lx", tcp->u_arg[1]);
404                 else
405                         printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
406         }
407         return 0;
408 }
409 #endif
410
411 int
412 sys_setitimer(struct tcb *tcp)
413 {
414         if (entering(tcp)) {
415                 printxval(which, tcp->u_arg[0], "ITIMER_???");
416                 tprintf(", ");
417                 printitv(tcp, tcp->u_arg[1]);
418                 tprintf(", ");
419         } else {
420                 if (syserror(tcp))
421                         tprintf("%#lx", tcp->u_arg[2]);
422                 else
423                         printitv(tcp, tcp->u_arg[2]);
424         }
425         return 0;
426 }
427
428 #ifdef ALPHA
429 int
430 sys_osf_setitimer(struct tcb *tcp)
431 {
432         if (entering(tcp)) {
433                 printxval(which, tcp->u_arg[0], "ITIMER_???");
434                 tprintf(", ");
435                 printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
436                 tprintf(", ");
437         } else {
438                 if (syserror(tcp))
439                         tprintf("%#lx", tcp->u_arg[2]);
440                 else
441                         printitv_bitness(tcp, tcp->u_arg[2], BITNESS_32);
442         }
443         return 0;
444 }
445 #endif
446
447 #ifdef LINUX
448
449 static const struct xlat adjtimex_modes[] = {
450   { 0, "0" },
451 #ifdef ADJ_OFFSET
452   { ADJ_OFFSET, "ADJ_OFFSET" },
453 #endif
454 #ifdef ADJ_FREQUENCY
455   { ADJ_FREQUENCY, "ADJ_FREQUENCY" },
456 #endif
457 #ifdef ADJ_MAXERROR
458   { ADJ_MAXERROR, "ADJ_MAXERROR" },
459 #endif
460 #ifdef ADJ_ESTERROR
461   { ADJ_ESTERROR, "ADJ_ESTERROR" },
462 #endif
463 #ifdef ADJ_STATUS
464   { ADJ_STATUS, "ADJ_STATUS" },
465 #endif
466 #ifdef ADJ_TIMECONST
467   { ADJ_TIMECONST, "ADJ_TIMECONST" },
468 #endif
469 #ifdef ADJ_TICK
470   { ADJ_TICK, "ADJ_TICK" },
471 #endif
472 #ifdef ADJ_OFFSET_SINGLESHOT
473   { ADJ_OFFSET_SINGLESHOT, "ADJ_OFFSET_SINGLESHOT" },
474 #endif
475   { 0,             NULL }
476 };
477
478 static const struct xlat adjtimex_status[] = {
479 #ifdef STA_PLL
480   { STA_PLL, "STA_PLL" },
481 #endif
482 #ifdef STA_PPSFREQ
483   { STA_PPSFREQ, "STA_PPSFREQ" },
484 #endif
485 #ifdef STA_PPSTIME
486   { STA_PPSTIME, "STA_PPSTIME" },
487 #endif
488 #ifdef STA_FLL
489   { STA_FLL, "STA_FLL" },
490 #endif
491 #ifdef STA_INS
492   { STA_INS, "STA_INS" },
493 #endif
494 #ifdef STA_DEL
495   { STA_DEL, "STA_DEL" },
496 #endif
497 #ifdef STA_UNSYNC
498   { STA_UNSYNC, "STA_UNSYNC" },
499 #endif
500 #ifdef STA_FREQHOLD
501   { STA_FREQHOLD, "STA_FREQHOLD" },
502 #endif
503 #ifdef STA_PPSSIGNAL
504   { STA_PPSSIGNAL, "STA_PPSSIGNAL" },
505 #endif
506 #ifdef STA_PPSJITTER
507   { STA_PPSJITTER, "STA_PPSJITTER" },
508 #endif
509 #ifdef STA_PPSWANDER
510   { STA_PPSWANDER, "STA_PPSWANDER" },
511 #endif
512 #ifdef STA_PPSERROR
513   { STA_PPSERROR, "STA_PPSERROR" },
514 #endif
515 #ifdef STA_CLOCKERR
516   { STA_CLOCKERR, "STA_CLOCKERR" },
517 #endif
518   { 0,             NULL }
519 };
520
521 static const struct xlat adjtimex_state[] = {
522 #ifdef TIME_OK
523   { TIME_OK, "TIME_OK" },
524 #endif
525 #ifdef TIME_INS
526   { TIME_INS, "TIME_INS" },
527 #endif
528 #ifdef TIME_DEL
529   { TIME_DEL, "TIME_DEL" },
530 #endif
531 #ifdef TIME_OOP
532   { TIME_OOP, "TIME_OOP" },
533 #endif
534 #ifdef TIME_WAIT
535   { TIME_WAIT, "TIME_WAIT" },
536 #endif
537 #ifdef TIME_ERROR
538   { TIME_ERROR, "TIME_ERROR" },
539 #endif
540   { 0,             NULL }
541 };
542
543 #if SUPPORTED_PERSONALITIES > 1
544 static int
545 tprint_timex32(struct tcb *tcp, long addr)
546 {
547         struct {
548                 unsigned int modes;
549                 int     offset;
550                 int     freq;
551                 int     maxerror;
552                 int     esterror;
553                 int     status;
554                 int     constant;
555                 int     precision;
556                 int     tolerance;
557                 struct timeval32 time;
558                 int     tick;
559                 int     ppsfreq;
560                 int     jitter;
561                 int     shift;
562                 int     stabil;
563                 int     jitcnt;
564                 int     calcnt;
565                 int     errcnt;
566                 int     stbcnt;
567         } tx;
568
569         if (umove(tcp, addr, &tx) < 0)
570                 return -1;
571
572         tprintf("{modes=");
573         printflags(adjtimex_modes, tx.modes, "ADJ_???");
574         tprintf(", offset=%d, freq=%d, maxerror=%d, ",
575                 tx.offset, tx.freq, tx.maxerror);
576         tprintf("esterror=%u, status=", tx.esterror);
577         printflags(adjtimex_status, tx.status, "STA_???");
578         tprintf(", constant=%d, precision=%u, ",
579                 tx.constant, tx.precision);
580         tprintf("tolerance=%d, time=", tx.tolerance);
581         tprint_timeval32(tcp, &tx.time);
582         tprintf(", tick=%d, ppsfreq=%d, jitter=%d",
583                 tx.tick, tx.ppsfreq, tx.jitter);
584         tprintf(", shift=%d, stabil=%d, jitcnt=%d",
585                 tx.shift, tx.stabil, tx.jitcnt);
586         tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d",
587                 tx.calcnt, tx.errcnt, tx.stbcnt);
588         tprintf("}");
589         return 0;
590 }
591 #endif /* SUPPORTED_PERSONALITIES > 1 */
592
593 static int
594 tprint_timex(struct tcb *tcp, long addr)
595 {
596         struct timex tx;
597
598 #if SUPPORTED_PERSONALITIES > 1
599         if (personality_wordsize[current_personality] == 4)
600                 return tprint_timex32(tcp, addr);
601 #endif
602         if (umove(tcp, addr, &tx) < 0)
603                 return -1;
604
605 #if LINUX_VERSION_CODE < 66332
606         tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
607                 tx.mode, tx.offset, tx.frequency);
608         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
609                 tx.maxerror, tx.esterror, tx.status);
610         tprintf("time_constant=%ld, precision=%lu, ",
611                 tx.time_constant, tx.precision);
612         tprintf("tolerance=%ld, time=", tx.tolerance);
613         tprint_timeval(tcp, &tx.time);
614 #else
615         tprintf("{modes=");
616         printflags(adjtimex_modes, tx.modes, "ADJ_???");
617         tprintf(", offset=%ld, freq=%ld, maxerror=%ld, ",
618                 tx.offset, tx.freq, tx.maxerror);
619         tprintf("esterror=%lu, status=", tx.esterror);
620         printflags(adjtimex_status, tx.status, "STA_???");
621         tprintf(", constant=%ld, precision=%lu, ",
622                 tx.constant, tx.precision);
623         tprintf("tolerance=%ld, time=", tx.tolerance);
624         tprint_timeval(tcp, &tx.time);
625         tprintf(", tick=%ld, ppsfreq=%ld, jitter=%ld",
626                 tx.tick, tx.ppsfreq, tx.jitter);
627         tprintf(", shift=%d, stabil=%ld, jitcnt=%ld",
628                 tx.shift, tx.stabil, tx.jitcnt);
629         tprintf(", calcnt=%ld, errcnt=%ld, stbcnt=%ld",
630                 tx.calcnt, tx.errcnt, tx.stbcnt);
631 #endif
632         tprintf("}");
633         return 0;
634 }
635
636 int
637 sys_adjtimex(struct tcb *tcp)
638 {
639         if (exiting(tcp)) {
640                 if (tcp->u_arg[0] == 0)
641                         tprintf("NULL");
642                 else if (syserror(tcp) || !verbose(tcp))
643                         tprintf("%#lx", tcp->u_arg[0]);
644                 else if (tprint_timex(tcp, tcp->u_arg[0]) < 0)
645                         tprintf("{...}");
646                 if (syserror(tcp))
647                         return 0;
648                 tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval);
649                 if (tcp->auxstr)
650                         return RVAL_STR;
651         }
652         return 0;
653 }
654
655 static const struct xlat clockflags[] = {
656   { TIMER_ABSTIME, "TIMER_ABSTIME" },
657   { 0,             NULL }
658 };
659
660 static const struct xlat clocknames[] = {
661 #ifdef CLOCK_REALTIME
662   { CLOCK_REALTIME, "CLOCK_REALTIME" },
663 #endif
664 #ifdef CLOCK_MONOTONIC
665   { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" },
666 #endif
667 #ifdef CLOCK_PROCESS_CPUTIME_ID
668   { CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID" },
669 #endif
670 #ifdef CLOCK_THREAD_CPUTIME_ID
671   { CLOCK_THREAD_CPUTIME_ID, "CLOCK_THREAD_CPUTIME_ID" },
672 #endif
673 #ifdef CLOCK_MONOTONIC_RAW
674   { CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW" },
675 #endif
676 #ifdef CLOCK_REALTIME_COARSE
677   { CLOCK_REALTIME_COARSE, "CLOCK_REALTIME_COARSE" },
678 #endif
679 #ifdef CLOCK_MONOTONIC_COARSE
680   { CLOCK_MONOTONIC_COARSE, "CLOCK_MONOTONIC_COARSE" },
681 #endif
682   { 0, NULL }
683 };
684
685 int
686 sys_clock_settime(struct tcb *tcp)
687 {
688         if (entering(tcp)) {
689                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
690                 tprintf(", ");
691                 printtv(tcp, tcp->u_arg[1]);
692         }
693         return 0;
694 }
695
696 int
697 sys_clock_gettime(struct tcb *tcp)
698 {
699         if (entering(tcp)) {
700                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
701                 tprintf(", ");
702         } else {
703                 if (syserror(tcp))
704                         tprintf("%#lx", tcp->u_arg[1]);
705                 else
706                         printtv(tcp, tcp->u_arg[1]);
707         }
708         return 0;
709 }
710
711 int
712 sys_clock_nanosleep(struct tcb *tcp)
713 {
714         if (entering(tcp)) {
715                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
716                 tprintf(", ");
717                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
718                 tprintf(", ");
719                 printtv(tcp, tcp->u_arg[2]);
720                 tprintf(", ");
721         } else {
722                 if (syserror(tcp))
723                         tprintf("%#lx", tcp->u_arg[3]);
724                 else
725                         printtv(tcp, tcp->u_arg[3]);
726         }
727         return 0;
728 }
729
730 #ifndef SIGEV_THREAD_ID
731 # define SIGEV_THREAD_ID 4
732 #endif
733 static const struct xlat sigev_value[] = {
734         { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
735         { SIGEV_NONE+1, "SIGEV_NONE" },
736         { SIGEV_THREAD+1, "SIGEV_THREAD" },
737         { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
738         { 0, NULL }
739 };
740
741 #if SUPPORTED_PERSONALITIES > 1
742 static void
743 printsigevent32(struct tcb *tcp, long arg)
744 {
745         struct {
746                 int     sigev_value;
747                 int     sigev_signo;
748                 int     sigev_notify;
749
750                 union {
751                         int     tid;
752                         struct {
753                                 int     function, attribute;
754                         } thread;
755                 } un;
756         } sev;
757
758         if (umove(tcp, arg, &sev) < 0)
759                 tprintf("{...}");
760         else {
761                 tprintf("{%#x, ", sev.sigev_value);
762                 if (sev.sigev_notify == SIGEV_SIGNAL)
763                         tprintf("%s, ", signame(sev.sigev_signo));
764                 else
765                         tprintf("%u, ", sev.sigev_signo);
766                 printxval(sigev_value, sev.sigev_notify + 1, "SIGEV_???");
767                 tprintf(", ");
768                 if (sev.sigev_notify == SIGEV_THREAD_ID)
769                         tprintf("{%d}", sev.un.tid);
770                 else if (sev.sigev_notify == SIGEV_THREAD)
771                         tprintf("{%#x, %#x}",
772                                 sev.un.thread.function,
773                                 sev.un.thread.attribute);
774                 else
775                         tprintf("{...}");
776                 tprintf("}");
777         }
778 }
779 #endif
780
781 void
782 printsigevent(struct tcb *tcp, long arg)
783 {
784         struct sigevent sev;
785
786 #if SUPPORTED_PERSONALITIES > 1
787         if (personality_wordsize[current_personality] == 4) {
788                 printsigevent32(tcp, arg);
789                 return;
790         }
791 #endif
792         if (umove(tcp, arg, &sev) < 0)
793                 tprintf("{...}");
794         else {
795                 tprintf("{%p, ", sev.sigev_value.sival_ptr);
796                 if (sev.sigev_notify == SIGEV_SIGNAL)
797                         tprintf("%s, ", signame(sev.sigev_signo));
798                 else
799                         tprintf("%u, ", sev.sigev_signo);
800                 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
801                 tprintf(", ");
802                 if (sev.sigev_notify == SIGEV_THREAD_ID)
803                         /* _pad[0] is the _tid field which might not be
804                            present in the userlevel definition of the
805                            struct.  */
806                         tprintf("{%d}", sev._sigev_un._pad[0]);
807                 else if (sev.sigev_notify == SIGEV_THREAD)
808                         tprintf("{%p, %p}", sev.sigev_notify_function,
809                                 sev.sigev_notify_attributes);
810                 else
811                         tprintf("{...}");
812                 tprintf("}");
813         }
814 }
815
816 int
817 sys_timer_create(struct tcb *tcp)
818 {
819         if (entering(tcp)) {
820                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
821                 tprintf(", ");
822                 printsigevent(tcp, tcp->u_arg[1]);
823                 tprintf(", ");
824         } else {
825                 int timer_id;
826
827                 if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &timer_id) < 0)
828                         tprintf("%#lx", tcp->u_arg[2]);
829                 else
830                         tprintf("{%d}", timer_id);
831         }
832         return 0;
833 }
834
835 int
836 sys_timer_settime(struct tcb *tcp)
837 {
838         if (entering(tcp)) {
839                 tprintf("%#lx, ", tcp->u_arg[0]);
840                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
841                 tprintf(", ");
842                 printitv(tcp, tcp->u_arg[2]);
843                 tprintf(", ");
844         } else {
845                 if (syserror(tcp))
846                         tprintf("%#lx", tcp->u_arg[3]);
847                 else
848                         printitv(tcp, tcp->u_arg[3]);
849         }
850         return 0;
851 }
852
853 int
854 sys_timer_gettime(struct tcb *tcp)
855 {
856         if (entering(tcp)) {
857                 tprintf("%#lx, ", tcp->u_arg[0]);
858         } else {
859                 if (syserror(tcp))
860                         tprintf("%#lx", tcp->u_arg[1]);
861                 else
862                         printitv(tcp, tcp->u_arg[1]);
863         }
864         return 0;
865 }
866
867 static void
868 print_rtc(struct tcb *tcp, const struct rtc_time *rt)
869 {
870         tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
871                 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
872                 rt->tm_sec, rt->tm_min, rt->tm_hour,
873                 rt->tm_mday, rt->tm_mon, rt->tm_year);
874         if (!abbrev(tcp))
875                 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
876                         rt->tm_wday, rt->tm_yday, rt->tm_isdst);
877         else
878                 tprintf("...}");
879 }
880
881 int
882 rtc_ioctl(struct tcb *tcp, long code, long arg)
883 {
884         switch (code) {
885         case RTC_ALM_SET:
886         case RTC_SET_TIME:
887                 if (entering(tcp)) {
888                         struct rtc_time rt;
889                         if (umove(tcp, arg, &rt) < 0)
890                                 tprintf(", %#lx", arg);
891                         else {
892                                 tprintf(", ");
893                                 print_rtc(tcp, &rt);
894                         }
895                 }
896                 break;
897         case RTC_ALM_READ:
898         case RTC_RD_TIME:
899                 if (exiting(tcp)) {
900                         struct rtc_time rt;
901                         if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
902                                 tprintf(", %#lx", arg);
903                         else {
904                                 tprintf(", ");
905                                 print_rtc(tcp, &rt);
906                         }
907                 }
908                 break;
909         case RTC_IRQP_SET:
910         case RTC_EPOCH_SET:
911                 if (entering(tcp))
912                         tprintf(", %lu", arg);
913                 break;
914         case RTC_IRQP_READ:
915         case RTC_EPOCH_READ:
916                 if (exiting(tcp))
917                         tprintf(", %lu", arg);
918                 break;
919         case RTC_WKALM_SET:
920                 if (entering(tcp)) {
921                         struct rtc_wkalrm wk;
922                         if (umove(tcp, arg, &wk) < 0)
923                                 tprintf(", %#lx", arg);
924                         else {
925                                 tprintf(", {enabled=%d, pending=%d, ",
926                                         wk.enabled, wk.pending);
927                                 print_rtc(tcp, &wk.time);
928                                 tprintf("}");
929                         }
930                 }
931                 break;
932         case RTC_WKALM_RD:
933                 if (exiting(tcp)) {
934                         struct rtc_wkalrm wk;
935                         if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
936                                 tprintf(", %#lx", arg);
937                         else {
938                                 tprintf(", {enabled=%d, pending=%d, ",
939                                         wk.enabled, wk.pending);
940                                 print_rtc(tcp, &wk.time);
941                                 tprintf("}");
942                         }
943                 }
944                 break;
945         default:
946                 if (entering(tcp))
947                         tprintf(", %#lx", arg);
948                 break;
949         }
950         return 1;
951 }
952
953 #ifndef TFD_TIMER_ABSTIME
954 #define TFD_TIMER_ABSTIME (1 << 0)
955 #endif
956
957 static const struct xlat timerfdflags[] = {
958         { TFD_TIMER_ABSTIME,    "TFD_TIMER_ABSTIME"     },
959         { 0,                    NULL                    }
960 };
961
962 int
963 sys_timerfd(struct tcb *tcp)
964 {
965         if (entering(tcp)) {
966                 /* It does not matter that the kernel uses itimerspec.  */
967                 tprintf("%ld, ", tcp->u_arg[0]);
968                 printxval(clocknames, tcp->u_arg[1], "CLOCK_???");
969                 tprintf(", ");
970                 printflags(timerfdflags, tcp->u_arg[2], "TFD_???");
971                 tprintf(", ");
972                 printitv(tcp, tcp->u_arg[3]);
973         }
974         return 0;
975 }
976
977 int
978 sys_timerfd_create(struct tcb *tcp)
979 {
980         if (entering(tcp)) {
981                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
982                 tprintf(", ");
983                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
984         }
985         return 0;
986 }
987
988 int
989 sys_timerfd_settime(struct tcb *tcp)
990 {
991         if (entering(tcp)) {
992                 printfd(tcp, tcp->u_arg[0]);
993                 tprintf(", ");
994                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
995                 tprintf(", ");
996                 printitv(tcp, tcp->u_arg[2]);
997                 tprintf(", ");
998                 printitv(tcp, tcp->u_arg[3]);
999         }
1000         return 0;
1001 }
1002
1003 int
1004 sys_timerfd_gettime(struct tcb *tcp)
1005 {
1006         if (entering(tcp)) {
1007                 printfd(tcp, tcp->u_arg[0]);
1008                 tprintf(", ");
1009                 printitv(tcp, tcp->u_arg[1]);
1010         }
1011         return 0;
1012 }
1013
1014 #endif /* LINUX */