thr_syscalls.c revision 127486
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: head/lib/libthr/thread/thr_syscalls.c 127486 2004-03-27 15:05:28Z mtm $
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
93extern int __creat(const char *, mode_t);
94extern int __sleep(unsigned int);
95extern int __sys_nanosleep(const struct timespec *, struct timespec *);
96extern int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
97extern int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
98extern int __system(const char *);
99extern int __tcdrain(int);
100extern pid_t __wait(int *);
101extern pid_t __sys_wait4(pid_t, int *, int, struct rusage *);
102extern pid_t __waitpid(pid_t, int *, int);
103
104__weak_reference(_aio_suspend, aio_suspend);
105
106int
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
121int
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
134int
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
148int
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
179int
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
193int
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
207int
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
222int
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
247int
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
259extern int __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
260		const struct timespec *timo, const sigset_t *mask);
261
262int
263pselect(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
277int
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
292ssize_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
306ssize_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
320int
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
335int
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
390unsigned 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
404int
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
419int
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
433pid_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
447pid_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
461pid_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
475ssize_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
489ssize_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