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