gcc-6: use $(GNU_ARCH) in manifest
[unleashed-userland.git] / tools / time.c
blob471eda6b962b8c57325053c17fca636e932a8fdb
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
21 * Copyright (c) 2010, Oracle and/or it's affiliates. All rights reserved.
25 * This compiles to a module that can be preloaded during a build. If this
26 * is preloaded, it interposes on time(2), gettimeofday(3C), and
27 * clock_gethrtime(3C) and returns a constant number of seconds since epoch
28 * when the execname matches one of the desired "programs" and TIME_CONSTANT
29 * contains an integer value to be returned.
32 #include <stdlib.h>
33 #include <ucontext.h>
34 #include <dlfcn.h>
35 #include <strings.h>
36 #include <time.h>
38 /* The list of programs that we want to use a constant time. */
39 static char *programs[] = {
40 "autogen", "bash", "cpp", "cc1", "date", "doxygen",
41 "erl", "grops", "gs", "gtroff", "javadoc", "ksh", "ksh93", "ld",
42 "perl", "perl5.8.4", "perl5.10", "ruby", "sh", NULL
45 static int
46 stack_info(uintptr_t pc, int signo, void *arg)
48 Dl_info info;
49 void *sym;
51 if (dladdr1((void *)pc, &info, &sym, RTLD_DL_SYMENT) != 0) {
52 if (strstr(info.dli_fname, ".so") == NULL)
53 *(char **)arg = (char *)info.dli_fname;
56 return (0);
59 static char *
60 my_execname()
62 static char *execname;
64 if (execname == NULL) {
65 ucontext_t ctx;
67 if (getcontext(&ctx) == 0)
68 walkcontext(&ctx, stack_info, &execname);
70 if (execname != NULL) {
71 char *s = strrchr(execname, '/');
73 if (s != NULL)
74 execname = ++s;
78 return (execname);
81 static time_t
82 time_constant()
84 char *execname = my_execname();
85 time_t result = -1;
87 if (execname != NULL) {
88 int i;
90 for (i = 0; programs[i] != NULL; i++)
91 if (strcmp(execname, programs[i]) == 0) {
92 static char *time_string;
94 if (time_string == NULL)
95 time_string = getenv("TIME_CONSTANT");
97 if (time_string != NULL)
98 result = atoll(time_string);
100 break;
104 return (result);
107 time_t
108 time(time_t *ptr)
110 time_t result = time_constant();
112 if (result == (time_t)-1) {
113 static time_t (*fptr)(time_t *);
115 if (fptr == NULL)
116 fptr = (time_t (*)(time_t *))dlsym(RTLD_NEXT, "time");
118 result = (fptr)(ptr);
119 } else if (ptr != NULL)
120 *ptr = result;
122 return (result);
126 gettimeofday(struct timeval *tp, void *tzp)
128 static int (*fptr)(struct timeval *, void *);
129 int result = -1;
131 if (fptr == NULL)
132 fptr = (int (*)(struct timeval *, void *))dlsym(RTLD_NEXT,
133 "gettimeofday");
135 if ((result = (fptr)(tp, tzp)) == 0) {
136 time_t curtime = time_constant();
138 if (curtime != (time_t)-1)
139 tp->tv_sec = curtime;
142 return (result);
146 clock_gettime(clockid_t clock_id, struct timespec *tp)
148 static int (*fptr)(clockid_t, struct timespec *);
149 int result = -1;
151 if (fptr == NULL)
152 fptr = (int (*)(clockid_t, struct timespec *))dlsym(RTLD_NEXT,
153 "clock_gettime");
155 if ((result = (fptr)(clock_id, tp)) == 0) {
156 time_t curtime = time_constant();
158 if (curtime != (time_t)-1)
159 tp->tv_sec = curtime;
162 return (result);