xref: /freebsd/lib/libthr/thread/thr_syscalls.c (revision 2357939bc239bd5334a169b62313806178dd8f30)
1 /*
2  * Copyright (c) 2000 Jason Evans <jasone@freebsd.org>.
3  * Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org>
4  * Copyright (c) 2003 Jeff Roberson <jeff@freebsd.org>
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(s), this list of conditions and the following disclaimer as
12  *    the first lines of this file unmodified other than the possible
13  *    addition of one or more copyright notices.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice(s), this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33 
34 /*
35  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
36  * All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. All advertising materials mentioning features or use of this software
47  *    must display the following acknowledgement:
48  *	This product includes software developed by John Birrell.
49  * 4. Neither the name of the author nor the names of any co-contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  */
66 
67 #include <sys/cdefs.h>
68 #include <sys/fcntl.h>
69 #include <sys/mman.h>
70 #include <sys/param.h>
71 #include <sys/select.h>
72 #include <sys/time.h>
73 #include <sys/types.h>
74 #include <sys/uio.h>
75 #include <sys/wait.h>
76 
77 #include <aio.h>
78 #include <dirent.h>
79 #include <errno.h>
80 #include <fcntl.h>
81 #include <poll.h>
82 #include <pthread.h>
83 #include <signal.h>
84 #include <stdarg.h>
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <string.h>
88 #include <termios.h>
89 #include <unistd.h>
90 
91 #include "thr_private.h"
92 
93 extern int __creat(const char *, mode_t);
94 extern int __sleep(unsigned int);
95 extern int __sys_nanosleep(const struct timespec *, struct timespec *);
96 extern int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
97 extern int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
98 extern int __system(const char *);
99 extern int __tcdrain(int);
100 extern pid_t __wait(int *);
101 extern pid_t __sys_wait4(pid_t, int *, int, struct rusage *);
102 extern pid_t __waitpid(pid_t, int *, int);
103 
104 __weak_reference(_aio_suspend, aio_suspend);
105 
106 int
107 _aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
108     timespec *timeout)
109 {
110 	int	ret;
111 
112 	_thread_enter_cancellation_point();
113 	ret = __sys_aio_suspend(iocbs, niocb, timeout);
114 	_thread_leave_cancellation_point();
115 
116 	return ret;
117 }
118 
119 __weak_reference(_close, close);
120 
121 int
122 _close(int fd)
123 {
124 	int	ret;
125 
126 	_thread_enter_cancellation_point();
127 	ret = __sys_close(fd);
128 	_thread_leave_cancellation_point();
129 
130 	return ret;
131 }
132 __weak_reference(_creat, creat);
133 
134 int
135 _creat(const char *path, mode_t mode)
136 {
137 	int	ret;
138 
139 	_thread_enter_cancellation_point();
140 	ret = __creat(path, mode);
141 	_thread_leave_cancellation_point();
142 
143 	return ret;
144 }
145 
146 __weak_reference(_fcntl, fcntl);
147 
148 int
149 _fcntl(int fd, int cmd,...)
150 {
151 	int	ret;
152 	va_list	ap;
153 
154 	_thread_enter_cancellation_point();
155 
156 	va_start(ap, cmd);
157 	switch (cmd) {
158 		case F_DUPFD:
159 		case F_SETFD:
160 		case F_SETFL:
161 			ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
162 			break;
163 		case F_GETFD:
164 		case F_GETFL:
165 			ret = __sys_fcntl(fd, cmd);
166 			break;
167 		default:
168 			ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
169 	}
170 	va_end(ap);
171 
172 	_thread_leave_cancellation_point();
173 
174 	return ret;
175 }
176 
177 __weak_reference(_fsync, fsync);
178 
179 int
180 _fsync(int fd)
181 {
182 	int	ret;
183 
184 	_thread_enter_cancellation_point();
185 	ret = __sys_fsync(fd);
186 	_thread_leave_cancellation_point();
187 
188 	return ret;
189 }
190 
191 __weak_reference(_msync, msync);
192 
193 int
194 _msync(void *addr, size_t len, int flags)
195 {
196 	int	ret;
197 
198 	_thread_enter_cancellation_point();
199 	ret = __sys_msync(addr, len, flags);
200 	_thread_leave_cancellation_point();
201 
202 	return ret;
203 }
204 
205 __weak_reference(_nanosleep, nanosleep);
206 
207 int
208 _nanosleep(const struct timespec * time_to_sleep, struct timespec *
209     time_remaining)
210 {
211 	int	ret;
212 
213 	_thread_enter_cancellation_point();
214 	ret = __sys_nanosleep(time_to_sleep, time_remaining);
215 	_thread_leave_cancellation_point();
216 
217 	return ret;
218 }
219 
220 __weak_reference(_open, open);
221 
222 int
223 _open(const char *path, int flags,...)
224 {
225 	int	ret;
226 	int	mode = 0;
227 	va_list	ap;
228 
229 	_thread_enter_cancellation_point();
230 
231 	/* Check if the file is being created: */
232 	if (flags & O_CREAT) {
233 		/* Get the creation mode: */
234 		va_start(ap, flags);
235 		mode = va_arg(ap, int);
236 		va_end(ap);
237 	}
238 
239 	ret = __sys_open(path, flags, mode);
240 	_thread_leave_cancellation_point();
241 
242 	return ret;
243 }
244 
245 __weak_reference(_poll, poll);
246 
247 int
248 _poll(struct pollfd *fds, unsigned int nfds, int timeout)
249 {
250 	int ret;
251 
252 	_thread_enter_cancellation_point();
253 	ret = __sys_poll(fds, nfds, timeout);
254 	_thread_leave_cancellation_point();
255 
256 	return ret;
257 }
258 
259 extern int __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
260 		const struct timespec *timo, const sigset_t *mask);
261 
262 int
263 pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
264 	const struct timespec *timo, const sigset_t *mask)
265 {
266 	int ret;
267 
268 	_thread_enter_cancellation_point();
269 	ret = __pselect(count, rfds, wfds, efds, timo, mask);
270 	_thread_leave_cancellation_point();
271 
272 	return (ret);
273 }
274 
275 __weak_reference(_raise, raise);
276 
277 int
278 _raise(int sig)
279 {
280 	int error;
281 
282 	error = pthread_kill(pthread_self(), sig);
283 	if (error != 0) {
284 		errno = error;
285 		error = -1;
286 	}
287 	return (error);
288 }
289 
290 __weak_reference(_read, read);
291 
292 ssize_t
293 _read(int fd, void *buf, size_t nbytes)
294 {
295 	ssize_t	ret;
296 
297 	_thread_enter_cancellation_point();
298 	ret = __sys_read(fd, buf, nbytes);
299 	_thread_leave_cancellation_point();
300 
301 	return ret;
302 }
303 
304 __weak_reference(_readv, readv);
305 
306 ssize_t
307 _readv(int fd, const struct iovec *iov, int iovcnt)
308 {
309 	ssize_t ret;
310 
311 	_thread_enter_cancellation_point();
312 	ret = __sys_readv(fd, iov, iovcnt);
313 	_thread_leave_cancellation_point();
314 
315 	return ret;
316 }
317 
318 __weak_reference(_select, select);
319 
320 int
321 _select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
322 	struct timeval *timeout)
323 {
324 	int ret;
325 
326 	_thread_enter_cancellation_point();
327 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
328 	_thread_leave_cancellation_point();
329 
330 	return ret;
331 }
332 
333 __weak_reference(_sigaction, sigaction);
334 
335 int
336 _sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
337 {
338 	struct sigaction *tmpact;
339 	struct sigaction oldact, wrapperact;
340 	int error;
341 
342 	/* Detect invalid signals. */
343 	if (sig < 1 || sig > NSIG) {
344 		errno = EINVAL;
345 		return (-1);
346 	}
347 
348 	/*
349 	 * If act is not NULL the library's signal wrapper is passed into the
350 	 * kernel only if the action is not SIG_DFL or SIG_IGN.
351 	 * On the other hand if act is NULL the caller only wants
352 	 * the old value so there is no need to call into the kernel.
353 	 */
354 	error = 0;
355 	tmpact = NULL;
356 	proc_sigact_copyout(sig, &oldact);
357 	if (act != NULL) {
358 		proc_sigact_copyin(sig, act);
359 		tmpact = proc_sigact_sigaction(sig);
360 		if (tmpact->sa_handler != SIG_DFL &&
361 		    tmpact->sa_handler != SIG_IGN) {
362 			bcopy((const void *)tmpact, (void *)&wrapperact,
363 			    sizeof(struct sigaction));
364 			wrapperact.sa_flags |= SA_SIGINFO;
365 			wrapperact.sa_sigaction = &_thread_sig_wrapper;
366 			tmpact = &wrapperact;
367 		}
368 		error = __sys_sigaction(sig, tmpact, NULL);
369 	}
370 	if (error == 0) {
371 
372 		/* If successful, return the old sigaction to the user */
373 		if (oact != NULL )
374 			bcopy((const void *)&oldact, (void *)oact,
375 			    sizeof(struct sigaction));
376 	} else {
377 
378 		/*
379 		 * The only time error is non-zero is if the syscall failed,
380 		 * which means the sigaction in the process global list
381 		 * was altered before the syscall. Return it to it's old value.
382 		 */
383 		proc_sigact_copyin(sig, &oldact);
384 	}
385 	return (error);
386 }
387 
388 __weak_reference(_sleep, sleep);
389 
390 unsigned int
391 _sleep(unsigned int seconds)
392 {
393 	unsigned int	ret;
394 
395 	_thread_enter_cancellation_point();
396 	ret = __sleep(seconds);
397 	_thread_leave_cancellation_point();
398 
399 	return ret;
400 }
401 
402 __weak_reference(_system, system);
403 
404 int
405 _system(const char *string)
406 {
407 	int	ret;
408 
409 	_thread_enter_cancellation_point();
410 	ret = __system(string);
411 	_thread_leave_cancellation_point();
412 
413 	return ret;
414 }
415 
416 
417 __weak_reference(_tcdrain, tcdrain);
418 
419 int
420 _tcdrain(int fd)
421 {
422 	int	ret;
423 
424 	_thread_enter_cancellation_point();
425 	ret = __tcdrain(fd);
426 	_thread_leave_cancellation_point();
427 
428 	return ret;
429 }
430 
431 __weak_reference(_wait, wait);
432 
433 pid_t
434 _wait(int *istat)
435 {
436 	pid_t	ret;
437 
438 	_thread_enter_cancellation_point();
439 	ret = __wait(istat);
440 	_thread_leave_cancellation_point();
441 
442 	return ret;
443 }
444 
445 __weak_reference(_wait4, wait4);
446 
447 pid_t
448 _wait4(pid_t pid, int *istat, int options, struct rusage *rusage)
449 {
450 	pid_t ret;
451 
452 	_thread_enter_cancellation_point();
453 	ret = __sys_wait4(pid, istat, options, rusage);
454 	_thread_leave_cancellation_point();
455 
456 	return ret;
457 }
458 
459 __weak_reference(_waitpid, waitpid);
460 
461 pid_t
462 _waitpid(pid_t wpid, int *status, int options)
463 {
464 	pid_t	ret;
465 
466 	_thread_enter_cancellation_point();
467 	ret = __waitpid(wpid, status, options);
468 	_thread_leave_cancellation_point();
469 
470 	return ret;
471 }
472 
473 __weak_reference(_write, write);
474 
475 ssize_t
476 _write(int fd, const void *buf, size_t nbytes)
477 {
478 	ssize_t	ret;
479 
480 	_thread_enter_cancellation_point();
481 	ret = __sys_write(fd, buf, nbytes);
482 	_thread_leave_cancellation_point();
483 
484 	return ret;
485 }
486 
487 __weak_reference(_writev, writev);
488 
489 ssize_t
490 _writev(int fd, const struct iovec *iov, int iovcnt)
491 {
492 	ssize_t ret;
493 
494 	_thread_enter_cancellation_point();
495 	ret = __sys_writev(fd, iov, iovcnt);
496 	_thread_leave_cancellation_point();
497 
498 	return ret;
499 }
500