thr_syscalls.c revision 281454
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 281454 2015-04-12 06:52:43Z 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
344static int
345__thr_kevent(int kq, const struct kevent *changelist, int nchanges,
346    struct kevent *eventlist, int nevents, const struct timespec *timeout)
347{
348	struct pthread *curthread;
349	int ret;
350
351	if (nevents == 0) {
352		/*
353		 * No blocking, do not make the call cancellable.
354		 */
355		return (__sys_kevent(kq, changelist, nchanges, eventlist,
356		    nevents, timeout));
357	}
358	curthread = _get_curthread();
359	_thr_cancel_enter(curthread);
360	ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
361	    timeout);
362	_thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
363
364	return (ret);
365}
366
367/*
368 * Cancellation behavior:
369 *   Thread may be canceled at start, but if the system call got some data,
370 *   the thread is not canceled.
371 */
372static ssize_t
373__thr_read(int fd, void *buf, size_t nbytes)
374{
375	struct pthread *curthread;
376	ssize_t	ret;
377
378	curthread = _get_curthread();
379	_thr_cancel_enter(curthread);
380	ret = __sys_read(fd, buf, nbytes);
381	_thr_cancel_leave(curthread, ret == -1);
382
383	return (ret);
384}
385
386/*
387 * Cancellation behavior:
388 *   Thread may be canceled at start, but if the system call got some data,
389 *   the thread is not canceled.
390 */
391static ssize_t
392__thr_readv(int fd, const struct iovec *iov, int iovcnt)
393{
394	struct pthread *curthread;
395	ssize_t ret;
396
397	curthread = _get_curthread();
398	_thr_cancel_enter(curthread);
399	ret = __sys_readv(fd, iov, iovcnt);
400	_thr_cancel_leave(curthread, ret == -1);
401	return (ret);
402}
403
404/*
405 * Cancellation behavior:
406 *   Thread may be canceled at start, but if the system call got some data,
407 *   the thread is not canceled.
408 */
409static ssize_t
410__thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
411    socklen_t *fl)
412{
413	struct pthread *curthread;
414	ssize_t ret;
415
416	curthread = _get_curthread();
417	_thr_cancel_enter(curthread);
418	ret = __sys_recvfrom(s, b, l, f, from, fl);
419	_thr_cancel_leave(curthread, ret == -1);
420	return (ret);
421}
422
423/*
424 * Cancellation behavior:
425 *   Thread may be canceled at start, but if the system call got some data,
426 *   the thread is not canceled.
427 */
428static ssize_t
429__thr_recvmsg(int s, struct msghdr *m, int f)
430{
431	struct pthread *curthread;
432	ssize_t ret;
433
434	curthread = _get_curthread();
435	_thr_cancel_enter(curthread);
436	ret = __sys_recvmsg(s, m, f);
437	_thr_cancel_leave(curthread, ret == -1);
438	return (ret);
439}
440
441/*
442 * Cancellation behavior:
443 *   Thread may be canceled at start, but if the system call returns something,
444 *   the thread is not canceled.
445 */
446static int
447__thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
448	struct timeval *timeout)
449{
450	struct pthread *curthread;
451	int ret;
452
453	curthread = _get_curthread();
454	_thr_cancel_enter(curthread);
455	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
456	_thr_cancel_leave(curthread, ret == -1);
457	return (ret);
458}
459
460/*
461 * Cancellation behavior:
462 *   Thread may be canceled at start, but if the system call sent
463 *   data, the thread is not canceled.
464 */
465static ssize_t
466__thr_sendmsg(int s, const struct msghdr *m, int f)
467{
468	struct pthread *curthread;
469	ssize_t ret;
470
471	curthread = _get_curthread();
472	_thr_cancel_enter(curthread);
473	ret = __sys_sendmsg(s, m, f);
474	_thr_cancel_leave(curthread, ret <= 0);
475	return (ret);
476}
477
478/*
479 * Cancellation behavior:
480 *   Thread may be canceled at start, but if the system call sent some
481 *   data, the thread is not canceled.
482 */
483static ssize_t
484__thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
485    socklen_t tl)
486{
487	struct pthread *curthread;
488	ssize_t ret;
489
490	curthread = _get_curthread();
491	_thr_cancel_enter(curthread);
492	ret = __sys_sendto(s, m, l, f, t, tl);
493	_thr_cancel_leave(curthread, ret <= 0);
494	return (ret);
495}
496
497static int
498__thr_system(const char *string)
499{
500	struct pthread *curthread;
501	int ret;
502
503	curthread = _get_curthread();
504	_thr_cancel_enter(curthread);
505	ret = __libc_system(string);
506	_thr_cancel_leave(curthread, 1);
507	return (ret);
508}
509
510/*
511 * Cancellation behavior:
512 *   If thread is canceled, the system call is not completed,
513 *   this means not all bytes were drained.
514 */
515static int
516__thr_tcdrain(int fd)
517{
518	struct pthread *curthread;
519	int ret;
520
521	curthread = _get_curthread();
522	_thr_cancel_enter(curthread);
523	ret = __libc_tcdrain(fd);
524	_thr_cancel_leave(curthread, ret == -1);
525	return (ret);
526}
527
528/*
529 * Cancellation behavior:
530 *   Thread may be canceled at start, but if the system call returns
531 *   a child pid, the thread is not canceled.
532 */
533static pid_t
534__thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
535{
536	struct pthread *curthread;
537	pid_t ret;
538
539	curthread = _get_curthread();
540	_thr_cancel_enter(curthread);
541	ret = __sys_wait4(pid, status, options, rusage);
542	_thr_cancel_leave(curthread, ret <= 0);
543	return (ret);
544}
545
546/*
547 * Cancellation behavior:
548 *   Thread may be canceled at start, but if the thread wrote some data,
549 *   it is not canceled.
550 */
551static ssize_t
552__thr_write(int fd, const void *buf, size_t nbytes)
553{
554	struct pthread *curthread;
555	ssize_t	ret;
556
557	curthread = _get_curthread();
558	_thr_cancel_enter(curthread);
559	ret = __sys_write(fd, buf, nbytes);
560	_thr_cancel_leave(curthread, (ret <= 0));
561	return (ret);
562}
563
564/*
565 * Cancellation behavior:
566 *   Thread may be canceled at start, but if the thread wrote some data,
567 *   it is not canceled.
568 */
569static ssize_t
570__thr_writev(int fd, const struct iovec *iov, int iovcnt)
571{
572	struct pthread *curthread;
573	ssize_t ret;
574
575	curthread = _get_curthread();
576	_thr_cancel_enter(curthread);
577	ret = __sys_writev(fd, iov, iovcnt);
578	_thr_cancel_leave(curthread, (ret <= 0));
579	return (ret);
580}
581
582void
583__thr_interpose_libc(void)
584{
585
586	__set_error_selector(__error_threaded);
587#define	SLOT(name)					\
588	*(__libc_interposing_slot(INTERPOS_##name)) =	\
589	    (interpos_func_t)__thr_##name;
590	SLOT(accept);
591	SLOT(accept4);
592	SLOT(aio_suspend);
593	SLOT(close);
594	SLOT(connect);
595	SLOT(fcntl);
596	SLOT(fsync);
597	SLOT(fork);
598	SLOT(msync);
599	SLOT(nanosleep);
600	SLOT(openat);
601	SLOT(poll);
602	SLOT(pselect);
603	SLOT(read);
604	SLOT(readv);
605	SLOT(recvfrom);
606	SLOT(recvmsg);
607	SLOT(select);
608	SLOT(sendmsg);
609	SLOT(sendto);
610	SLOT(setcontext);
611	SLOT(sigaction);
612	SLOT(sigprocmask);
613	SLOT(sigsuspend);
614	SLOT(sigwait);
615	SLOT(sigtimedwait);
616	SLOT(sigwaitinfo);
617	SLOT(swapcontext);
618	SLOT(system);
619	SLOT(tcdrain);
620	SLOT(wait4);
621	SLOT(write);
622	SLOT(writev);
623	SLOT(spinlock);
624	SLOT(spinunlock);
625	SLOT(kevent);
626#undef SLOT
627	*(__libc_interposing_slot(
628	    INTERPOS__pthread_mutex_init_calloc_cb)) =
629	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
630}
631