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