xref: /freebsd/lib/libthr/thread/thr_syscalls.c (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
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 spinlock_t *__malloc_lock;
94 
95 extern int __creat(const char *, mode_t);
96 extern int __sleep(unsigned int);
97 extern int __sys_nanosleep(const struct timespec *, struct timespec *);
98 extern int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
99 extern int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
100 extern int __system(const char *);
101 extern int __tcdrain(int);
102 extern pid_t __wait(int *);
103 extern pid_t __sys_wait4(pid_t, int *, int, struct rusage *);
104 extern pid_t __waitpid(pid_t, int *, int);
105 
106 __weak_reference(_aio_suspend, aio_suspend);
107 
108 int
109 _aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
110     timespec *timeout)
111 {
112 	int	ret;
113 
114 	_thread_enter_cancellation_point();
115 	ret = __sys_aio_suspend(iocbs, niocb, timeout);
116 	_thread_leave_cancellation_point();
117 
118 	return ret;
119 }
120 
121 __weak_reference(_close, close);
122 
123 int
124 _close(int fd)
125 {
126 	int	ret;
127 
128 	_thread_enter_cancellation_point();
129 	ret = __sys_close(fd);
130 	_thread_leave_cancellation_point();
131 
132 	return ret;
133 }
134 __weak_reference(_creat, creat);
135 
136 int
137 _creat(const char *path, mode_t mode)
138 {
139 	int	ret;
140 
141 	_thread_enter_cancellation_point();
142 	ret = __creat(path, mode);
143 	_thread_leave_cancellation_point();
144 
145 	return ret;
146 }
147 
148 __weak_reference(_fcntl, fcntl);
149 
150 int
151 _fcntl(int fd, int cmd,...)
152 {
153 	int	ret;
154 	va_list	ap;
155 
156 	_thread_enter_cancellation_point();
157 
158 	va_start(ap, cmd);
159 	switch (cmd) {
160 		case F_DUPFD:
161 		case F_SETFD:
162 		case F_SETFL:
163 			ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
164 			break;
165 		case F_GETFD:
166 		case F_GETFL:
167 			ret = __sys_fcntl(fd, cmd);
168 			break;
169 		default:
170 			ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
171 	}
172 	va_end(ap);
173 
174 	_thread_leave_cancellation_point();
175 
176 	return ret;
177 }
178 
179 __weak_reference(_fork, fork);
180 
181 int
182 _fork(int fd)
183 {
184 	int	ret;
185 	struct pthread_atfork *af;
186 
187 	_pthread_mutex_lock(&_atfork_mutex);
188 
189 	/* Run down atfork prepare handlers. */
190 	TAILQ_FOREACH_REVERSE(af, &_atfork_list, atfork_head, qe) {
191 		if (af->prepare != NULL)
192 			af->prepare();
193 	}
194 
195  	/*
196 	 * Fork a new process.
197 	 * XXX - The correct way to handle __malloc_lock is to have
198 	 *	 the threads libraries (or libc) install fork handlers for it
199 	 *	 in their initialization routine. We should probably
200 	 *	 do that for all the locks in libc.
201 	 */
202 	if (__isthreaded && __malloc_lock != NULL)
203 		_SPINLOCK(__malloc_lock);
204 	ret = __sys_fork();
205  	if (ret == 0) {
206 		__isthreaded = 0;
207 		if (__malloc_lock != NULL)
208 			memset(__malloc_lock, 0, sizeof(spinlock_t));
209 		init_tdlist(curthread, 1);
210 		init_td_common(curthread, NULL, 1);
211 		_mutex_reinit(&_atfork_mutex);
212 
213 		/* Run down atfork child handlers. */
214 		TAILQ_FOREACH(af, &_atfork_list, qe) {
215 			if (af->child != NULL)
216 				af->child();
217 		}
218  	} else if (ret != -1) {
219 		/* Run down atfork parent handlers. */
220 		TAILQ_FOREACH(af, &_atfork_list, qe) {
221 			if (af->parent != NULL)
222 			af->parent();
223 		}
224 	}
225 
226 	if (ret != 0) {
227 		if (__isthreaded && __malloc_lock != NULL)
228 			_SPINUNLOCK(__malloc_lock);
229 		_pthread_mutex_unlock(&_atfork_mutex);
230 	}
231 	return ret;
232 }
233 
234 
235 __weak_reference(_fsync, fsync);
236 
237 int
238 _fsync(int fd)
239 {
240 	int	ret;
241 
242 	_thread_enter_cancellation_point();
243 	ret = __sys_fsync(fd);
244 	_thread_leave_cancellation_point();
245 
246 	return ret;
247 }
248 
249 __weak_reference(_msync, msync);
250 
251 int
252 _msync(void *addr, size_t len, int flags)
253 {
254 	int	ret;
255 
256 	_thread_enter_cancellation_point();
257 	ret = __sys_msync(addr, len, flags);
258 	_thread_leave_cancellation_point();
259 
260 	return ret;
261 }
262 
263 __weak_reference(_nanosleep, nanosleep);
264 
265 int
266 _nanosleep(const struct timespec * time_to_sleep, struct timespec *
267     time_remaining)
268 {
269 	int	ret;
270 
271 	_thread_enter_cancellation_point();
272 	ret = __sys_nanosleep(time_to_sleep, time_remaining);
273 	_thread_leave_cancellation_point();
274 
275 	return ret;
276 }
277 
278 __weak_reference(_open, open);
279 
280 int
281 _open(const char *path, int flags,...)
282 {
283 	int	ret;
284 	int	mode = 0;
285 	va_list	ap;
286 
287 	_thread_enter_cancellation_point();
288 
289 	/* Check if the file is being created: */
290 	if (flags & O_CREAT) {
291 		/* Get the creation mode: */
292 		va_start(ap, flags);
293 		mode = va_arg(ap, int);
294 		va_end(ap);
295 	}
296 
297 	ret = __sys_open(path, flags, mode);
298 	_thread_leave_cancellation_point();
299 
300 	return ret;
301 }
302 
303 __weak_reference(_poll, poll);
304 
305 int
306 _poll(struct pollfd *fds, unsigned int nfds, int timeout)
307 {
308 	int ret;
309 
310 	_thread_enter_cancellation_point();
311 	ret = __sys_poll(fds, nfds, timeout);
312 	_thread_leave_cancellation_point();
313 
314 	return ret;
315 }
316 
317 extern int __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
318 		const struct timespec *timo, const sigset_t *mask);
319 
320 int
321 pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
322 	const struct timespec *timo, const sigset_t *mask)
323 {
324 	int ret;
325 
326 	_thread_enter_cancellation_point();
327 	ret = __pselect(count, rfds, wfds, efds, timo, mask);
328 	_thread_leave_cancellation_point();
329 
330 	return (ret);
331 }
332 
333 __weak_reference(_raise, raise);
334 
335 int
336 _raise(int sig)
337 {
338 	int error;
339 
340 	error = pthread_kill(pthread_self(), sig);
341 	if (error != 0) {
342 		errno = error;
343 		error = -1;
344 	}
345 	return (error);
346 }
347 
348 __weak_reference(_read, read);
349 
350 ssize_t
351 _read(int fd, void *buf, size_t nbytes)
352 {
353 	ssize_t	ret;
354 
355 	_thread_enter_cancellation_point();
356 	ret = __sys_read(fd, buf, nbytes);
357 	_thread_leave_cancellation_point();
358 
359 	return ret;
360 }
361 
362 __weak_reference(_readv, readv);
363 
364 ssize_t
365 _readv(int fd, const struct iovec *iov, int iovcnt)
366 {
367 	ssize_t ret;
368 
369 	_thread_enter_cancellation_point();
370 	ret = __sys_readv(fd, iov, iovcnt);
371 	_thread_leave_cancellation_point();
372 
373 	return ret;
374 }
375 
376 __weak_reference(_select, select);
377 
378 int
379 _select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
380 	struct timeval *timeout)
381 {
382 	int ret;
383 
384 	_thread_enter_cancellation_point();
385 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
386 	_thread_leave_cancellation_point();
387 
388 	return ret;
389 }
390 
391 __weak_reference(_sleep, sleep);
392 
393 unsigned int
394 _sleep(unsigned int seconds)
395 {
396 	unsigned int	ret;
397 
398 	_thread_enter_cancellation_point();
399 	ret = __sleep(seconds);
400 	_thread_leave_cancellation_point();
401 
402 	return ret;
403 }
404 
405 __weak_reference(_system, system);
406 
407 int
408 _system(const char *string)
409 {
410 	int	ret;
411 
412 	_thread_enter_cancellation_point();
413 	ret = __system(string);
414 	_thread_leave_cancellation_point();
415 
416 	return ret;
417 }
418 
419 
420 __weak_reference(_tcdrain, tcdrain);
421 
422 int
423 _tcdrain(int fd)
424 {
425 	int	ret;
426 
427 	_thread_enter_cancellation_point();
428 	ret = __tcdrain(fd);
429 	_thread_leave_cancellation_point();
430 
431 	return ret;
432 }
433 
434 __weak_reference(_wait, wait);
435 
436 pid_t
437 _wait(int *istat)
438 {
439 	pid_t	ret;
440 
441 	_thread_enter_cancellation_point();
442 	ret = __wait(istat);
443 	_thread_leave_cancellation_point();
444 
445 	return ret;
446 }
447 
448 __weak_reference(_wait4, wait4);
449 
450 pid_t
451 _wait4(pid_t pid, int *istat, int options, struct rusage *rusage)
452 {
453 	pid_t ret;
454 
455 	_thread_enter_cancellation_point();
456 	ret = __sys_wait4(pid, istat, options, rusage);
457 	_thread_leave_cancellation_point();
458 
459 	return ret;
460 }
461 
462 __weak_reference(_waitpid, waitpid);
463 
464 pid_t
465 _waitpid(pid_t wpid, int *status, int options)
466 {
467 	pid_t	ret;
468 
469 	_thread_enter_cancellation_point();
470 	ret = __waitpid(wpid, status, options);
471 	_thread_leave_cancellation_point();
472 
473 	return ret;
474 }
475 
476 __weak_reference(_write, write);
477 
478 ssize_t
479 _write(int fd, const void *buf, size_t nbytes)
480 {
481 	ssize_t	ret;
482 
483 	_thread_enter_cancellation_point();
484 	ret = __sys_write(fd, buf, nbytes);
485 	_thread_leave_cancellation_point();
486 
487 	return ret;
488 }
489 
490 __weak_reference(_writev, writev);
491 
492 ssize_t
493 _writev(int fd, const struct iovec *iov, int iovcnt)
494 {
495 	ssize_t ret;
496 
497 	_thread_enter_cancellation_point();
498 	ret = __sys_writev(fd, iov, iovcnt);
499 	_thread_leave_cancellation_point();
500 
501 	return ret;
502 }
503