xref: /freebsd/lib/libthr/thread/thr_syscalls.c (revision f6a4109212fd8fbabc731f07b2dd5c7e07fbec33)
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(_read, read);
276 
277 ssize_t
278 _read(int fd, void *buf, size_t nbytes)
279 {
280 	ssize_t	ret;
281 
282 	_thread_enter_cancellation_point();
283 	ret = __sys_read(fd, buf, nbytes);
284 	_thread_leave_cancellation_point();
285 
286 	return ret;
287 }
288 
289 __weak_reference(_readv, readv);
290 
291 ssize_t
292 _readv(int fd, const struct iovec *iov, int iovcnt)
293 {
294 	ssize_t ret;
295 
296 	_thread_enter_cancellation_point();
297 	ret = __sys_readv(fd, iov, iovcnt);
298 	_thread_leave_cancellation_point();
299 
300 	return ret;
301 }
302 
303 __weak_reference(_select, select);
304 
305 int
306 _select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
307 	struct timeval *timeout)
308 {
309 	int ret;
310 
311 	_thread_enter_cancellation_point();
312 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
313 	_thread_leave_cancellation_point();
314 
315 	return ret;
316 }
317 
318 __weak_reference(_sigaction, sigaction);
319 
320 int
321 _sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
322 {
323 	struct sigaction *tmpact;
324 	struct sigaction oldact, wrapperact;
325 	int error;
326 
327 	/* Detect invalid signals. Signal SIGTHR is silently ignored */
328 	if (sig < 1 || sig > NSIG) {
329 		errno = EINVAL;
330 		return (-1);
331 	}
332 	if (sig == SIGTHR)
333 		return (0);
334 
335 	/*
336 	 * If act is not NULL the library's signal wrapper is passed into the
337 	 * kernel only if the action is not SIG_DFL or SIG_IGN.
338 	 * On the other hand if act is NULL the caller only wants
339 	 * the old value so there is no need to call into the kernel.
340 	 */
341 	error = 0;
342 	tmpact = NULL;
343 	proc_sigact_copyout(sig, &oldact);
344 	if (act != NULL) {
345 		proc_sigact_copyin(sig, act);
346 		tmpact = proc_sigact_sigaction(sig);
347 		if (tmpact->sa_handler != SIG_DFL &&
348 		    tmpact->sa_handler != SIG_IGN) {
349 			bcopy((const void *)tmpact, (void *)&wrapperact,
350 			    sizeof(struct sigaction));
351 			tmpact->sa_flags &= SA_SIGINFO;
352 			wrapperact.sa_sigaction = &_thread_sig_wrapper;
353 			tmpact = &wrapperact;
354 		}
355 		error = __sys_sigaction(sig, tmpact, NULL);
356 	}
357 	if (error == 0) {
358 
359 		/* If successful, return the old sigaction to the user */
360 		if (oact != NULL )
361 			bcopy((const void *)&oldact, (void *)oact,
362 			    sizeof(struct sigaction));
363 	} else {
364 
365 		/*
366 		 * The only time error is non-zero is if the syscall failed,
367 		 * which means the sigaction in the process global list
368 		 * was altered before the syscall. Return it to it's old value.
369 		 */
370 		proc_sigact_copyin(sig, &oldact);
371 	}
372 	return (error);
373 }
374 
375 __weak_reference(_sleep, sleep);
376 
377 unsigned int
378 _sleep(unsigned int seconds)
379 {
380 	unsigned int	ret;
381 
382 	_thread_enter_cancellation_point();
383 	ret = __sleep(seconds);
384 	_thread_leave_cancellation_point();
385 
386 	return ret;
387 }
388 
389 __weak_reference(_system, system);
390 
391 int
392 _system(const char *string)
393 {
394 	int	ret;
395 
396 	_thread_enter_cancellation_point();
397 	ret = __system(string);
398 	_thread_leave_cancellation_point();
399 
400 	return ret;
401 }
402 
403 
404 __weak_reference(_tcdrain, tcdrain);
405 
406 int
407 _tcdrain(int fd)
408 {
409 	int	ret;
410 
411 	_thread_enter_cancellation_point();
412 	ret = __tcdrain(fd);
413 	_thread_leave_cancellation_point();
414 
415 	return ret;
416 }
417 
418 __weak_reference(_wait, wait);
419 
420 pid_t
421 _wait(int *istat)
422 {
423 	pid_t	ret;
424 
425 	_thread_enter_cancellation_point();
426 	ret = __wait(istat);
427 	_thread_leave_cancellation_point();
428 
429 	return ret;
430 }
431 
432 __weak_reference(_wait4, wait4);
433 
434 pid_t
435 _wait4(pid_t pid, int *istat, int options, struct rusage *rusage)
436 {
437 	pid_t ret;
438 
439 	_thread_enter_cancellation_point();
440 	ret = __sys_wait4(pid, istat, options, rusage);
441 	_thread_leave_cancellation_point();
442 
443 	return ret;
444 }
445 
446 __weak_reference(_waitpid, waitpid);
447 
448 pid_t
449 _waitpid(pid_t wpid, int *status, int options)
450 {
451 	pid_t	ret;
452 
453 	_thread_enter_cancellation_point();
454 	ret = __waitpid(wpid, status, options);
455 	_thread_leave_cancellation_point();
456 
457 	return ret;
458 }
459 
460 __weak_reference(_write, write);
461 
462 ssize_t
463 _write(int fd, const void *buf, size_t nbytes)
464 {
465 	ssize_t	ret;
466 
467 	_thread_enter_cancellation_point();
468 	ret = __sys_write(fd, buf, nbytes);
469 	_thread_leave_cancellation_point();
470 
471 	return ret;
472 }
473 
474 __weak_reference(_writev, writev);
475 
476 ssize_t
477 _writev(int fd, const struct iovec *iov, int iovcnt)
478 {
479 	ssize_t ret;
480 
481 	_thread_enter_cancellation_point();
482 	ret = __sys_writev(fd, iov, iovcnt);
483 	_thread_leave_cancellation_point();
484 
485 	return ret;
486 }
487