thr_syscalls.c revision 277317
1/*
2 * Copyright (c) 2014 The FreeBSD Foundation.
3 * Copyright (C) 2005 David Xu <davidxu@freebsd.org>.
4 * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>.
5 * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
6 * All rights reserved.
7 *
8 * Portions of this software were developed by Konstantin Belousov
9 * under sponsorship from the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice(s), this list of conditions and the following disclaimer as
16 *    the first lines of this file unmodified other than the possible
17 *    addition of one or more copyright notices.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice(s), this list of conditions and the following disclaimer in
20 *    the documentation and/or other materials provided with the
21 *    distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36/*
37 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
38 * All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 *    notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 *    notice, this list of conditions and the following disclaimer in the
47 *    documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the author nor the names of any co-contributors
49 *    may be used to endorse or promote products derived from this software
50 *    without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 */
65
66#include <sys/cdefs.h>
67__FBSDID("$FreeBSD: stable/10/lib/libthr/thread/thr_syscalls.c 277317 2015-01-18 11:54:20Z kib $");
68
69#include "namespace.h"
70#include <sys/types.h>
71#include <sys/mman.h>
72#include <sys/param.h>
73#include <sys/select.h>
74#include <sys/signalvar.h>
75#include <sys/socket.h>
76#include <sys/stat.h>
77#include <sys/time.h>
78#include <sys/uio.h>
79#include <sys/wait.h>
80#include <aio.h>
81#include <dirent.h>
82#include <errno.h>
83#include <fcntl.h>
84#include <poll.h>
85#include <signal.h>
86#include <stdarg.h>
87#include <stdio.h>
88#include <stdlib.h>
89#include <string.h>
90#include <termios.h>
91#include <unistd.h>
92#include <pthread.h>
93#include "un-namespace.h"
94
95#include "libc_private.h"
96#include "thr_private.h"
97
98#ifdef SYSCALL_COMPAT
99extern int __fcntl_compat(int, int, ...);
100#endif
101
102static int
103__thr_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
104{
105	struct pthread *curthread;
106	int ret;
107
108	curthread = _get_curthread();
109	_thr_cancel_enter(curthread);
110	ret = __sys_accept(s, addr, addrlen);
111	_thr_cancel_leave(curthread, ret == -1);
112
113 	return (ret);
114}
115
116/*
117 * Cancellation behavior:
118 *   If thread is canceled, no socket is created.
119 */
120static int
121__thr_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
122{
123	struct pthread *curthread;
124	int ret;
125
126	curthread = _get_curthread();
127	_thr_cancel_enter(curthread);
128	ret = __sys_accept4(s, addr, addrlen, flags);
129	_thr_cancel_leave(curthread, ret == -1);
130
131 	return (ret);
132}
133
134static int
135__thr_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
136    timespec *timeout)
137{
138	struct pthread *curthread;
139	int ret;
140
141	curthread = _get_curthread();
142	_thr_cancel_enter(curthread);
143	ret = __sys_aio_suspend(iocbs, niocb, timeout);
144	_thr_cancel_leave(curthread, 1);
145
146	return (ret);
147}
148
149/*
150 * Cancellation behavior:
151 *   According to manual of close(), the file descriptor is always deleted.
152 *   Here, thread is only canceled after the system call, so the file
153 *   descriptor is always deleted despite whether the thread is canceled
154 *   or not.
155 */
156static int
157__thr_close(int fd)
158{
159	struct pthread *curthread;
160	int ret;
161
162	curthread = _get_curthread();
163	_thr_cancel_enter2(curthread, 0);
164	ret = __sys_close(fd);
165	_thr_cancel_leave(curthread, 1);
166
167	return (ret);
168}
169
170/*
171 * Cancellation behavior:
172 *   If the thread is canceled, connection is not made.
173 */
174static int
175__thr_connect(int fd, const struct sockaddr *name, socklen_t namelen)
176{
177	struct pthread *curthread;
178	int ret;
179
180	curthread = _get_curthread();
181	_thr_cancel_enter(curthread);
182	ret = __sys_connect(fd, name, namelen);
183	_thr_cancel_leave(curthread, ret == -1);
184
185 	return (ret);
186}
187
188/*
189 * Cancellation behavior:
190 *   According to specification, only F_SETLKW is a cancellation point.
191 *   Thread is only canceled at start, or canceled if the system call
192 *   is failure, this means the function does not generate side effect
193 *   if it is canceled.
194 */
195static int
196__thr_fcntl(int fd, int cmd, ...)
197{
198	struct pthread *curthread;
199	int ret;
200	va_list	ap;
201
202	curthread = _get_curthread();
203	va_start(ap, cmd);
204	if (cmd == F_OSETLKW || cmd == F_SETLKW) {
205		_thr_cancel_enter(curthread);
206#ifdef SYSCALL_COMPAT
207		ret = __fcntl_compat(fd, cmd, va_arg(ap, void *));
208#else
209		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
210#endif
211		_thr_cancel_leave(curthread, ret == -1);
212	} else {
213#ifdef SYSCALL_COMPAT
214		ret = __fcntl_compat(fd, cmd, va_arg(ap, void *));
215#else
216		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
217#endif
218	}
219	va_end(ap);
220
221	return (ret);
222}
223
224/*
225 * Cancellation behavior:
226 *   Thread may be canceled after system call.
227 */
228static int
229__thr_fsync(int fd)
230{
231	struct pthread *curthread;
232	int ret;
233
234	curthread = _get_curthread();
235	_thr_cancel_enter2(curthread, 0);
236	ret = __sys_fsync(fd);
237	_thr_cancel_leave(curthread, 1);
238
239	return (ret);
240}
241
242/*
243 * Cancellation behavior:
244 *   Thread may be canceled after system call.
245 */
246static int
247__thr_msync(void *addr, size_t len, int flags)
248{
249	struct pthread *curthread;
250	int ret;
251
252	curthread = _get_curthread();
253	_thr_cancel_enter2(curthread, 0);
254	ret = __sys_msync(addr, len, flags);
255	_thr_cancel_leave(curthread, 1);
256
257	return (ret);
258}
259
260static int
261__thr_nanosleep(const struct timespec *time_to_sleep,
262    struct timespec *time_remaining)
263{
264	struct pthread *curthread;
265	int ret;
266
267	curthread = _get_curthread();
268	_thr_cancel_enter(curthread);
269	ret = __sys_nanosleep(time_to_sleep, time_remaining);
270	_thr_cancel_leave(curthread, 1);
271
272	return (ret);
273}
274
275/*
276 * Cancellation behavior:
277 *   If the thread is canceled, file is not opened.
278 */
279static int
280__thr_openat(int fd, const char *path, int flags, ...)
281{
282	struct pthread *curthread;
283	int mode, ret;
284	va_list	ap;
285
286
287	/* Check if the file is being created: */
288	if ((flags & O_CREAT) != 0) {
289		/* Get the creation mode: */
290		va_start(ap, flags);
291		mode = va_arg(ap, int);
292		va_end(ap);
293	} else {
294		mode = 0;
295	}
296
297	curthread = _get_curthread();
298	_thr_cancel_enter(curthread);
299	ret = __sys_openat(fd, path, flags, mode);
300	_thr_cancel_leave(curthread, ret == -1);
301
302	return (ret);
303}
304
305/*
306 * Cancellation behavior:
307 *   Thread may be canceled at start, but if the system call returns something,
308 *   the thread is not canceled.
309 */
310static int
311__thr_poll(struct pollfd *fds, unsigned int nfds, int timeout)
312{
313	struct pthread *curthread;
314	int ret;
315
316	curthread = _get_curthread();
317	_thr_cancel_enter(curthread);
318	ret = __sys_poll(fds, nfds, timeout);
319	_thr_cancel_leave(curthread, ret == -1);
320
321	return (ret);
322}
323
324/*
325 * Cancellation behavior:
326 *   Thread may be canceled at start, but if the system call returns something,
327 *   the thread is not canceled.
328 */
329static int
330__thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
331	const struct timespec *timo, const sigset_t *mask)
332{
333	struct pthread *curthread;
334	int ret;
335
336	curthread = _get_curthread();
337	_thr_cancel_enter(curthread);
338	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
339	_thr_cancel_leave(curthread, ret == -1);
340
341	return (ret);
342}
343
344/*
345 * Cancellation behavior:
346 *   Thread may be canceled at start, but if the system call got some data,
347 *   the thread is not canceled.
348 */
349static ssize_t
350__thr_read(int fd, void *buf, size_t nbytes)
351{
352	struct pthread *curthread;
353	ssize_t	ret;
354
355	curthread = _get_curthread();
356	_thr_cancel_enter(curthread);
357	ret = __sys_read(fd, buf, nbytes);
358	_thr_cancel_leave(curthread, ret == -1);
359
360	return (ret);
361}
362
363/*
364 * Cancellation behavior:
365 *   Thread may be canceled at start, but if the system call got some data,
366 *   the thread is not canceled.
367 */
368static ssize_t
369__thr_readv(int fd, const struct iovec *iov, int iovcnt)
370{
371	struct pthread *curthread;
372	ssize_t ret;
373
374	curthread = _get_curthread();
375	_thr_cancel_enter(curthread);
376	ret = __sys_readv(fd, iov, iovcnt);
377	_thr_cancel_leave(curthread, ret == -1);
378	return (ret);
379}
380
381/*
382 * Cancellation behavior:
383 *   Thread may be canceled at start, but if the system call got some data,
384 *   the thread is not canceled.
385 */
386static ssize_t
387__thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
388    socklen_t *fl)
389{
390	struct pthread *curthread;
391	ssize_t ret;
392
393	curthread = _get_curthread();
394	_thr_cancel_enter(curthread);
395	ret = __sys_recvfrom(s, b, l, f, from, fl);
396	_thr_cancel_leave(curthread, ret == -1);
397	return (ret);
398}
399
400/*
401 * Cancellation behavior:
402 *   Thread may be canceled at start, but if the system call got some data,
403 *   the thread is not canceled.
404 */
405static ssize_t
406__thr_recvmsg(int s, struct msghdr *m, int f)
407{
408	struct pthread *curthread;
409	ssize_t ret;
410
411	curthread = _get_curthread();
412	_thr_cancel_enter(curthread);
413	ret = __sys_recvmsg(s, m, f);
414	_thr_cancel_leave(curthread, ret == -1);
415	return (ret);
416}
417
418/*
419 * Cancellation behavior:
420 *   Thread may be canceled at start, but if the system call returns something,
421 *   the thread is not canceled.
422 */
423static int
424__thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
425	struct timeval *timeout)
426{
427	struct pthread *curthread;
428	int ret;
429
430	curthread = _get_curthread();
431	_thr_cancel_enter(curthread);
432	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
433	_thr_cancel_leave(curthread, ret == -1);
434	return (ret);
435}
436
437/*
438 * Cancellation behavior:
439 *   Thread may be canceled at start, but if the system call sent
440 *   data, the thread is not canceled.
441 */
442static ssize_t
443__thr_sendmsg(int s, const struct msghdr *m, int f)
444{
445	struct pthread *curthread;
446	ssize_t ret;
447
448	curthread = _get_curthread();
449	_thr_cancel_enter(curthread);
450	ret = __sys_sendmsg(s, m, f);
451	_thr_cancel_leave(curthread, ret <= 0);
452	return (ret);
453}
454
455/*
456 * Cancellation behavior:
457 *   Thread may be canceled at start, but if the system call sent some
458 *   data, the thread is not canceled.
459 */
460static ssize_t
461__thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
462    socklen_t tl)
463{
464	struct pthread *curthread;
465	ssize_t ret;
466
467	curthread = _get_curthread();
468	_thr_cancel_enter(curthread);
469	ret = __sys_sendto(s, m, l, f, t, tl);
470	_thr_cancel_leave(curthread, ret <= 0);
471	return (ret);
472}
473
474static int
475__thr_system(const char *string)
476{
477	struct pthread *curthread;
478	int ret;
479
480	curthread = _get_curthread();
481	_thr_cancel_enter(curthread);
482	ret = __libc_system(string);
483	_thr_cancel_leave(curthread, 1);
484	return (ret);
485}
486
487/*
488 * Cancellation behavior:
489 *   If thread is canceled, the system call is not completed,
490 *   this means not all bytes were drained.
491 */
492static int
493__thr_tcdrain(int fd)
494{
495	struct pthread *curthread;
496	int ret;
497
498	curthread = _get_curthread();
499	_thr_cancel_enter(curthread);
500	ret = __libc_tcdrain(fd);
501	_thr_cancel_leave(curthread, ret == -1);
502	return (ret);
503}
504
505/*
506 * Cancellation behavior:
507 *   Thread may be canceled at start, but if the system call returns
508 *   a child pid, the thread is not canceled.
509 */
510static pid_t
511__thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
512{
513	struct pthread *curthread;
514	pid_t ret;
515
516	curthread = _get_curthread();
517	_thr_cancel_enter(curthread);
518	ret = __sys_wait4(pid, status, options, rusage);
519	_thr_cancel_leave(curthread, ret <= 0);
520	return (ret);
521}
522
523/*
524 * Cancellation behavior:
525 *   Thread may be canceled at start, but if the thread wrote some data,
526 *   it is not canceled.
527 */
528static ssize_t
529__thr_write(int fd, const void *buf, size_t nbytes)
530{
531	struct pthread *curthread;
532	ssize_t	ret;
533
534	curthread = _get_curthread();
535	_thr_cancel_enter(curthread);
536	ret = __sys_write(fd, buf, nbytes);
537	_thr_cancel_leave(curthread, (ret <= 0));
538	return (ret);
539}
540
541/*
542 * Cancellation behavior:
543 *   Thread may be canceled at start, but if the thread wrote some data,
544 *   it is not canceled.
545 */
546static ssize_t
547__thr_writev(int fd, const struct iovec *iov, int iovcnt)
548{
549	struct pthread *curthread;
550	ssize_t ret;
551
552	curthread = _get_curthread();
553	_thr_cancel_enter(curthread);
554	ret = __sys_writev(fd, iov, iovcnt);
555	_thr_cancel_leave(curthread, (ret <= 0));
556	return (ret);
557}
558
559void
560__thr_interpose_libc(void)
561{
562
563	__set_error_selector(__error_threaded);
564#define	SLOT(name)					\
565	*(__libc_interposing_slot(INTERPOS_##name)) =	\
566	    (interpos_func_t)__thr_##name;
567	SLOT(accept);
568	SLOT(accept4);
569	SLOT(aio_suspend);
570	SLOT(close);
571	SLOT(connect);
572	SLOT(fcntl);
573	SLOT(fsync);
574	SLOT(fork);
575	SLOT(msync);
576	SLOT(nanosleep);
577	SLOT(openat);
578	SLOT(poll);
579	SLOT(pselect);
580	SLOT(read);
581	SLOT(readv);
582	SLOT(recvfrom);
583	SLOT(recvmsg);
584	SLOT(select);
585	SLOT(sendmsg);
586	SLOT(sendto);
587	SLOT(setcontext);
588	SLOT(sigaction);
589	SLOT(sigprocmask);
590	SLOT(sigsuspend);
591	SLOT(sigwait);
592	SLOT(sigtimedwait);
593	SLOT(sigwaitinfo);
594	SLOT(swapcontext);
595	SLOT(system);
596	SLOT(tcdrain);
597	SLOT(wait4);
598	SLOT(write);
599	SLOT(writev);
600#undef SLOT
601	*(__libc_interposing_slot(
602	    INTERPOS__pthread_mutex_init_calloc_cb)) =
603	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
604}
605