| @@ -1,331 +1,337 @@ | | | @@ -1,331 +1,337 @@ |
1 | /* $NetBSD: thunk.c,v 1.19 2011/08/25 11:06:29 jmcneill Exp $ */ | | 1 | /* $NetBSD: thunk.c,v 1.20 2011/08/27 21:14:15 reinoud Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> | | 4 | * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. | | 26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | __RCSID("$NetBSD: thunk.c,v 1.19 2011/08/25 11:06:29 jmcneill Exp $"); | | 30 | __RCSID("$NetBSD: thunk.c,v 1.20 2011/08/27 21:14:15 reinoud Exp $"); |
31 | | | 31 | |
32 | #include <sys/types.h> | | 32 | #include <sys/types.h> |
33 | #include <sys/ansi.h> | | 33 | #include <sys/ansi.h> |
34 | | | 34 | |
35 | #include <aio.h> | | 35 | #include <aio.h> |
36 | #include <assert.h> | | 36 | #include <assert.h> |
37 | #include <fcntl.h> | | 37 | #include <fcntl.h> |
38 | #include <stdarg.h> | | 38 | #include <stdarg.h> |
39 | #include <stdint.h> | | 39 | #include <stdint.h> |
40 | #include <stdio.h> | | 40 | #include <stdio.h> |
41 | #include <stdlib.h> | | 41 | #include <stdlib.h> |
42 | #include <signal.h> | | 42 | #include <signal.h> |
43 | #include <time.h> | | 43 | #include <time.h> |
44 | #include <ucontext.h> | | 44 | #include <ucontext.h> |
45 | #include <unistd.h> | | 45 | #include <unistd.h> |
46 | | | 46 | |
47 | #include "../include/thunk.h" | | 47 | #include "../include/thunk.h" |
48 | | | 48 | |
49 | static void | | 49 | static void |
50 | thunk_to_timeval(const struct thunk_timeval *ttv, struct timeval *tv) | | 50 | thunk_to_timeval(const struct thunk_timeval *ttv, struct timeval *tv) |
51 | { | | 51 | { |
52 | tv->tv_sec = ttv->tv_sec; | | 52 | tv->tv_sec = ttv->tv_sec; |
53 | tv->tv_usec = ttv->tv_usec; | | 53 | tv->tv_usec = ttv->tv_usec; |
54 | } | | 54 | } |
55 | | | 55 | |
56 | static void | | 56 | static void |
57 | thunk_from_timeval(const struct timeval *tv, struct thunk_timeval *ttv) | | 57 | thunk_from_timeval(const struct timeval *tv, struct thunk_timeval *ttv) |
58 | { | | 58 | { |
59 | ttv->tv_sec = tv->tv_sec; | | 59 | ttv->tv_sec = tv->tv_sec; |
60 | ttv->tv_usec = tv->tv_usec; | | 60 | ttv->tv_usec = tv->tv_usec; |
61 | } | | 61 | } |
62 | | | 62 | |
63 | static void | | 63 | static void |
64 | thunk_to_itimerval(const struct thunk_itimerval *tit, struct itimerval *it) | | 64 | thunk_to_itimerval(const struct thunk_itimerval *tit, struct itimerval *it) |
65 | { | | 65 | { |
66 | thunk_to_timeval(&tit->it_interval, &it->it_interval); | | 66 | thunk_to_timeval(&tit->it_interval, &it->it_interval); |
67 | thunk_to_timeval(&tit->it_value, &it->it_value); | | 67 | thunk_to_timeval(&tit->it_value, &it->it_value); |
68 | } | | 68 | } |
69 | | | 69 | |
70 | static void | | 70 | static void |
71 | thunk_from_itimerval(const struct itimerval *it, struct thunk_itimerval *tit) | | 71 | thunk_from_itimerval(const struct itimerval *it, struct thunk_itimerval *tit) |
72 | { | | 72 | { |
73 | thunk_from_timeval(&it->it_interval, &tit->it_interval); | | 73 | thunk_from_timeval(&it->it_interval, &tit->it_interval); |
74 | thunk_from_timeval(&it->it_value, &tit->it_value); | | 74 | thunk_from_timeval(&it->it_value, &tit->it_value); |
75 | } | | 75 | } |
76 | | | 76 | |
77 | int | | 77 | int |
78 | thunk_setitimer(int which, const struct thunk_itimerval *value, | | 78 | thunk_setitimer(int which, const struct thunk_itimerval *value, |
79 | struct thunk_itimerval *ovalue) | | 79 | struct thunk_itimerval *ovalue) |
80 | { | | 80 | { |
81 | struct itimerval it, oit; | | 81 | struct itimerval it, oit; |
82 | int error; | | 82 | int error; |
83 | | | 83 | |
84 | thunk_to_itimerval(value, &it); | | 84 | thunk_to_itimerval(value, &it); |
85 | error = setitimer(which, &it, &oit); | | 85 | error = setitimer(which, &it, &oit); |
86 | if (error) | | 86 | if (error) |
87 | return error; | | 87 | return error; |
88 | if (ovalue) | | 88 | if (ovalue) |
89 | thunk_from_itimerval(&oit, ovalue); | | 89 | thunk_from_itimerval(&oit, ovalue); |
90 | | | 90 | |
91 | return 0; | | 91 | return 0; |
92 | } | | 92 | } |
93 | | | 93 | |
94 | int | | 94 | int |
95 | thunk_gettimeofday(struct thunk_timeval *tp, void *tzp) | | 95 | thunk_gettimeofday(struct thunk_timeval *tp, void *tzp) |
96 | { | | 96 | { |
97 | struct timeval tv; | | 97 | struct timeval tv; |
98 | int error; | | 98 | int error; |
99 | | | 99 | |
100 | error = gettimeofday(&tv, tzp); | | 100 | error = gettimeofday(&tv, tzp); |
101 | if (error) | | 101 | if (error) |
102 | return error; | | 102 | return error; |
103 | | | 103 | |
104 | thunk_from_timeval(&tv, tp); | | 104 | thunk_from_timeval(&tv, tp); |
105 | | | 105 | |
106 | return 0; | | 106 | return 0; |
107 | } | | 107 | } |
108 | | | 108 | |
109 | unsigned int | | 109 | unsigned int |
110 | thunk_getcounter(void) | | 110 | thunk_getcounter(void) |
111 | { | | 111 | { |
112 | struct timespec ts; | | 112 | struct timespec ts; |
113 | int error; | | 113 | int error; |
114 | | | 114 | |
115 | error = clock_gettime(CLOCK_MONOTONIC, &ts); | | 115 | error = clock_gettime(CLOCK_MONOTONIC, &ts); |
116 | if (error) { | | 116 | if (error) { |
117 | perror("clock_gettime CLOCK_MONOTONIC"); | | 117 | perror("clock_gettime CLOCK_MONOTONIC"); |
118 | abort(); | | 118 | abort(); |
119 | } | | 119 | } |
120 | | | 120 | |
121 | return (unsigned int)(ts.tv_sec * 1000000000ULL + ts.tv_nsec); | | 121 | return (unsigned int)(ts.tv_sec * 1000000000ULL + ts.tv_nsec); |
122 | } | | 122 | } |
123 | | | 123 | |
124 | long | | 124 | long |
125 | thunk_clock_getres_monotonic(void) | | 125 | thunk_clock_getres_monotonic(void) |
126 | { | | 126 | { |
127 | struct timespec res; | | 127 | struct timespec res; |
128 | int error; | | 128 | int error; |
129 | | | 129 | |
130 | error = clock_getres(CLOCK_MONOTONIC, &res); | | 130 | error = clock_getres(CLOCK_MONOTONIC, &res); |
131 | if (error) | | 131 | if (error) |
132 | return -1; | | 132 | return -1; |
133 | | | 133 | |
134 | return res.tv_nsec; | | 134 | return res.tv_nsec; |
135 | } | | 135 | } |
136 | | | 136 | |
137 | int | | 137 | int |
138 | thunk_usleep(useconds_t microseconds) | | 138 | thunk_usleep(useconds_t microseconds) |
139 | { | | 139 | { |
140 | return usleep(microseconds); | | 140 | return usleep(microseconds); |
141 | } | | 141 | } |
142 | | | 142 | |
143 | void | | 143 | void |
144 | thunk_exit(int status) | | 144 | thunk_exit(int status) |
145 | { | | 145 | { |
146 | return exit(status); | | 146 | return exit(status); |
147 | } | | 147 | } |
148 | | | 148 | |
149 | void | | 149 | void |
150 | thunk_abort(void) | | 150 | thunk_abort(void) |
151 | { | | 151 | { |
152 | abort(); | | 152 | abort(); |
153 | } | | 153 | } |
154 | | | 154 | |
155 | int | | 155 | int |
156 | thunk_getcontext(ucontext_t *ucp) | | 156 | thunk_getcontext(ucontext_t *ucp) |
157 | { | | 157 | { |
158 | return getcontext(ucp); | | 158 | return getcontext(ucp); |
159 | } | | 159 | } |
160 | | | 160 | |
161 | int | | 161 | int |
162 | thunk_setcontext(const ucontext_t *ucp) | | 162 | thunk_setcontext(const ucontext_t *ucp) |
163 | { | | 163 | { |
164 | return setcontext(ucp); | | 164 | return setcontext(ucp); |
165 | } | | 165 | } |
166 | | | 166 | |
167 | void | | 167 | void |
168 | thunk_makecontext(ucontext_t *ucp, void (*func)(void), int argc, | | 168 | thunk_makecontext(ucontext_t *ucp, void (*func)(void), int argc, |
169 | void (*arg1)(void *), void *arg2) | | 169 | void (*arg1)(void *), void *arg2) |
170 | { | | 170 | { |
171 | assert(argc == 2); | | 171 | assert(argc == 2); |
172 | | | 172 | |
173 | makecontext(ucp, func, argc, arg1, arg2); | | 173 | makecontext(ucp, func, argc, arg1, arg2); |
174 | } | | 174 | } |
175 | | | 175 | |
176 | int | | 176 | int |
177 | thunk_swapcontext(ucontext_t *oucp, ucontext_t *ucp) | | 177 | thunk_swapcontext(ucontext_t *oucp, ucontext_t *ucp) |
178 | { | | 178 | { |
179 | return swapcontext(oucp, ucp); | | 179 | return swapcontext(oucp, ucp); |
180 | } | | 180 | } |
181 | | | 181 | |
182 | int | | 182 | int |
183 | thunk_getchar(void) | | 183 | thunk_getchar(void) |
184 | { | | 184 | { |
185 | return getchar(); | | 185 | return getchar(); |
186 | } | | 186 | } |
187 | | | 187 | |
188 | void | | 188 | void |
189 | thunk_putchar(int c) | | 189 | thunk_putchar(int c) |
190 | { | | 190 | { |
191 | char wc = (char) c; | | 191 | char wc = (char) c; |
192 | write(1, &wc, 1); | | 192 | write(1, &wc, 1); |
193 | } | | 193 | } |
194 | | | 194 | |
195 | int | | 195 | int |
196 | thunk_execv(const char *path, char * const argv[]) | | 196 | thunk_execv(const char *path, char * const argv[]) |
197 | { | | 197 | { |
198 | return execv(path, argv); | | 198 | return execv(path, argv); |
199 | } | | 199 | } |
200 | | | 200 | |
201 | int | | 201 | int |
202 | thunk_open(const char *path, int flags, mode_t mode) | | 202 | thunk_open(const char *path, int flags, mode_t mode) |
203 | { | | 203 | { |
204 | return open(path, flags, mode); | | 204 | return open(path, flags, mode); |
205 | } | | 205 | } |
206 | | | 206 | |
207 | int | | 207 | int |
208 | thunk_fstat_getsize(int fd, ssize_t *size, ssize_t *blksize) | | 208 | thunk_fstat_getsize(int fd, ssize_t *size, ssize_t *blksize) |
209 | { | | 209 | { |
210 | struct stat st; | | 210 | struct stat st; |
211 | int error; | | 211 | int error; |
212 | | | 212 | |
213 | error = fstat(fd, &st); | | 213 | error = fstat(fd, &st); |
214 | if (error) | | 214 | if (error) |
215 | return -1; | | 215 | return -1; |
216 | | | 216 | |
217 | if (size) | | 217 | if (size) |
218 | *size = st.st_size; | | 218 | *size = st.st_size; |
219 | if (blksize) | | 219 | if (blksize) |
220 | *blksize = st.st_blksize; | | 220 | *blksize = st.st_blksize; |
221 | | | 221 | |
222 | return 0; | | 222 | return 0; |
223 | } | | 223 | } |
224 | | | 224 | |
225 | ssize_t | | 225 | ssize_t |
226 | thunk_pread(int d, void *buf, size_t nbytes, off_t offset) | | 226 | thunk_pread(int d, void *buf, size_t nbytes, off_t offset) |
227 | { | | 227 | { |
228 | return pread(d, buf, nbytes, offset); | | 228 | return pread(d, buf, nbytes, offset); |
229 | } | | 229 | } |
230 | | | 230 | |
231 | ssize_t | | 231 | ssize_t |
232 | thunk_pwrite(int d, const void *buf, size_t nbytes, off_t offset) | | 232 | thunk_pwrite(int d, const void *buf, size_t nbytes, off_t offset) |
233 | { | | 233 | { |
234 | return pwrite(d, buf, nbytes, offset); | | 234 | return pwrite(d, buf, nbytes, offset); |
235 | } | | 235 | } |
236 | | | 236 | |
237 | int | | 237 | int |
238 | thunk_fsync(int fd) | | 238 | thunk_fsync(int fd) |
239 | { | | 239 | { |
240 | return fsync(fd); | | 240 | return fsync(fd); |
241 | } | | 241 | } |
242 | | | 242 | |
243 | int | | 243 | int |
244 | thunk_mkstemp(char *template) | | 244 | thunk_mkstemp(char *template) |
245 | { | | 245 | { |
246 | return mkstemp(template); | | 246 | return mkstemp(template); |
247 | } | | 247 | } |
248 | | | 248 | |
249 | int | | 249 | int |
250 | thunk_unlink(const char *path) | | 250 | thunk_unlink(const char *path) |
251 | { | | 251 | { |
252 | return unlink(path); | | 252 | return unlink(path); |
253 | } | | 253 | } |
254 | | | 254 | |
255 | int | | 255 | int |
256 | thunk_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) | | 256 | thunk_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) |
257 | { | | 257 | { |
258 | return sigaction(sig, act, oact); | | 258 | return sigaction(sig, act, oact); |
259 | } | | 259 | } |
260 | | | 260 | |
261 | void | | 261 | void |
262 | thunk_signal(int sig, void (*func)(int)) | | 262 | thunk_signal(int sig, void (*func)(int)) |
263 | { | | 263 | { |
264 | signal(sig, func); | | 264 | signal(sig, func); |
265 | } | | 265 | } |
266 | | | 266 | |
267 | int | | 267 | int |
| | | 268 | thunk_atexit(void (*function)(void)) |
| | | 269 | { |
| | | 270 | return atexit(function); |
| | | 271 | } |
| | | 272 | |
| | | 273 | int |
268 | thunk_aio_read(struct aiocb *aiocbp) | | 274 | thunk_aio_read(struct aiocb *aiocbp) |
269 | { | | 275 | { |
270 | return aio_read(aiocbp); | | 276 | return aio_read(aiocbp); |
271 | } | | 277 | } |
272 | | | 278 | |
273 | int | | 279 | int |
274 | thunk_aio_write(struct aiocb *aiocbp) | | 280 | thunk_aio_write(struct aiocb *aiocbp) |
275 | { | | 281 | { |
276 | return aio_write(aiocbp); | | 282 | return aio_write(aiocbp); |
277 | } | | 283 | } |
278 | | | 284 | |
279 | int | | 285 | int |
280 | thunk_aio_error(const struct aiocb *aiocbp) | | 286 | thunk_aio_error(const struct aiocb *aiocbp) |
281 | { | | 287 | { |
282 | return aio_error(aiocbp); | | 288 | return aio_error(aiocbp); |
283 | } | | 289 | } |
284 | | | 290 | |
285 | int | | 291 | int |
286 | thunk_aio_return(struct aiocb *aiocbp) | | 292 | thunk_aio_return(struct aiocb *aiocbp) |
287 | { | | 293 | { |
288 | return aio_return(aiocbp); | | 294 | return aio_return(aiocbp); |
289 | } | | 295 | } |
290 | | | 296 | |
291 | void * | | 297 | void * |
292 | thunk_malloc(size_t len) | | 298 | thunk_malloc(size_t len) |
293 | { | | 299 | { |
294 | return malloc(len); | | 300 | return malloc(len); |
295 | } | | 301 | } |
296 | | | 302 | |
297 | void | | 303 | void |
298 | thunk_free(void *addr) | | 304 | thunk_free(void *addr) |
299 | { | | 305 | { |
300 | free(addr); | | 306 | free(addr); |
301 | } | | 307 | } |
302 | | | 308 | |
303 | void * | | 309 | void * |
304 | thunk_sbrk(intptr_t len) | | 310 | thunk_sbrk(intptr_t len) |
305 | { | | 311 | { |
306 | return sbrk(len); | | 312 | return sbrk(len); |
307 | } | | 313 | } |
308 | | | 314 | |
309 | void * | | 315 | void * |
310 | thunk_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) | | 316 | thunk_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) |
311 | { | | 317 | { |
312 | return mmap(addr, len, prot, flags, fd, offset); | | 318 | return mmap(addr, len, prot, flags, fd, offset); |
313 | } | | 319 | } |
314 | | | 320 | |
315 | int | | 321 | int |
316 | thunk_munmap(void *addr, size_t len) | | 322 | thunk_munmap(void *addr, size_t len) |
317 | { | | 323 | { |
318 | return munmap(addr, len); | | 324 | return munmap(addr, len); |
319 | } | | 325 | } |
320 | | | 326 | |
321 | int | | 327 | int |
322 | thunk_mprotect(void *addr, size_t len, int prot) | | 328 | thunk_mprotect(void *addr, size_t len, int prot) |
323 | { | | 329 | { |
324 | return mprotect(addr, len, prot); | | 330 | return mprotect(addr, len, prot); |
325 | } | | 331 | } |
326 | | | 332 | |
327 | char * | | 333 | char * |
328 | thunk_getenv(const char *name) | | 334 | thunk_getenv(const char *name) |
329 | { | | 335 | { |
330 | return getenv(name); | | 336 | return getenv(name); |
331 | } | | 337 | } |