xref: /freebsd/lib/libthr/thread/thr_syscalls.c (revision a56fe703c2065069cf756bbafcb3dc35c25f5343)
1bb535300SJeff Roberson /*
28495e8b1SKonstantin Belousov  * Copyright (c) 2014 The FreeBSD Foundation.
3a091d823SDavid Xu  * Copyright (C) 2005 David Xu <davidxu@freebsd.org>.
4a091d823SDavid Xu  * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>.
5a091d823SDavid Xu  * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
6bb535300SJeff Roberson  * All rights reserved.
7bb535300SJeff Roberson  *
88495e8b1SKonstantin Belousov  * Portions of this software were developed by Konstantin Belousov
98495e8b1SKonstantin Belousov  * under sponsorship from the FreeBSD Foundation.
108495e8b1SKonstantin Belousov  *
11bb535300SJeff Roberson  * Redistribution and use in source and binary forms, with or without
12bb535300SJeff Roberson  * modification, are permitted provided that the following conditions
13bb535300SJeff Roberson  * are met:
14bb535300SJeff Roberson  * 1. Redistributions of source code must retain the above copyright
15bb535300SJeff Roberson  *    notice(s), this list of conditions and the following disclaimer as
16bb535300SJeff Roberson  *    the first lines of this file unmodified other than the possible
17bb535300SJeff Roberson  *    addition of one or more copyright notices.
18bb535300SJeff Roberson  * 2. Redistributions in binary form must reproduce the above copyright
19bb535300SJeff Roberson  *    notice(s), this list of conditions and the following disclaimer in
20bb535300SJeff Roberson  *    the documentation and/or other materials provided with the
21bb535300SJeff Roberson  *    distribution.
22bb535300SJeff Roberson  *
23bb535300SJeff Roberson  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
24bb535300SJeff Roberson  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25bb535300SJeff Roberson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26bb535300SJeff Roberson  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
27bb535300SJeff Roberson  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28bb535300SJeff Roberson  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29bb535300SJeff Roberson  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30bb535300SJeff Roberson  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31bb535300SJeff Roberson  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32bb535300SJeff Roberson  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33bb535300SJeff Roberson  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34bb535300SJeff Roberson  */
35bb535300SJeff Roberson 
368a16b7a1SPedro F. Giffuni /*-
378a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
388a16b7a1SPedro F. Giffuni  *
39bb535300SJeff Roberson  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
40bb535300SJeff Roberson  * All rights reserved.
41bb535300SJeff Roberson  *
42bb535300SJeff Roberson  * Redistribution and use in source and binary forms, with or without
43bb535300SJeff Roberson  * modification, are permitted provided that the following conditions
44bb535300SJeff Roberson  * are met:
45bb535300SJeff Roberson  * 1. Redistributions of source code must retain the above copyright
46bb535300SJeff Roberson  *    notice, this list of conditions and the following disclaimer.
47bb535300SJeff Roberson  * 2. Redistributions in binary form must reproduce the above copyright
48bb535300SJeff Roberson  *    notice, this list of conditions and the following disclaimer in the
49bb535300SJeff Roberson  *    documentation and/or other materials provided with the distribution.
50fed32d75SWarner Losh  * 3. Neither the name of the author nor the names of any co-contributors
51bb535300SJeff Roberson  *    may be used to endorse or promote products derived from this software
52bb535300SJeff Roberson  *    without specific prior written permission.
53bb535300SJeff Roberson  *
54bb535300SJeff Roberson  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
55bb535300SJeff Roberson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56bb535300SJeff Roberson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57bb535300SJeff Roberson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
58bb535300SJeff Roberson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59bb535300SJeff Roberson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60bb535300SJeff Roberson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61bb535300SJeff Roberson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62bb535300SJeff Roberson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63bb535300SJeff Roberson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64bb535300SJeff Roberson  * SUCH DAMAGE.
65bb535300SJeff Roberson  *
66bb535300SJeff Roberson  */
67bb535300SJeff Roberson 
6837a6356bSDavid Xu #include "namespace.h"
69bb535300SJeff Roberson #include <sys/param.h>
70*a56fe703SKonstantin Belousov #include <sys/exterrvar.h>
71*a56fe703SKonstantin Belousov #include <sys/mman.h>
72bb535300SJeff Roberson #include <sys/select.h>
73a091d823SDavid Xu #include <sys/signalvar.h>
74737afa3cSMike Makonnen #include <sys/socket.h>
75a091d823SDavid Xu #include <sys/stat.h>
76bb535300SJeff Roberson #include <sys/time.h>
77bb535300SJeff Roberson #include <sys/uio.h>
78bb535300SJeff Roberson #include <sys/wait.h>
79bb535300SJeff Roberson #include <aio.h>
80bb535300SJeff Roberson #include <dirent.h>
81bb535300SJeff Roberson #include <errno.h>
82bb535300SJeff Roberson #include <fcntl.h>
83bb535300SJeff Roberson #include <poll.h>
84bb535300SJeff Roberson #include <signal.h>
85bb535300SJeff Roberson #include <stdarg.h>
86bb535300SJeff Roberson #include <stdio.h>
87bb535300SJeff Roberson #include <stdlib.h>
88bb535300SJeff Roberson #include <string.h>
89bb535300SJeff Roberson #include <termios.h>
90bb535300SJeff Roberson #include <unistd.h>
91a091d823SDavid Xu #include <pthread.h>
9237a6356bSDavid Xu #include "un-namespace.h"
93bb535300SJeff Roberson 
948495e8b1SKonstantin Belousov #include "libc_private.h"
95bb535300SJeff Roberson #include "thr_private.h"
96bb535300SJeff Roberson 
978495e8b1SKonstantin Belousov static int
__thr_accept(int s,struct sockaddr * addr,socklen_t * addrlen)988495e8b1SKonstantin Belousov __thr_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
99737afa3cSMike Makonnen {
100a091d823SDavid Xu 	struct pthread *curthread;
101737afa3cSMike Makonnen 	int ret;
102737afa3cSMike Makonnen 
103a091d823SDavid Xu 	curthread = _get_curthread();
10402c3c858SDavid Xu 	_thr_cancel_enter(curthread);
105737afa3cSMike Makonnen 	ret = __sys_accept(s, addr, addrlen);
10602c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
107a091d823SDavid Xu 
108737afa3cSMike Makonnen  	return (ret);
109737afa3cSMike Makonnen }
110737afa3cSMike Makonnen 
111da7d2afbSJilles Tjoelker /*
112da7d2afbSJilles Tjoelker  * Cancellation behavior:
113da7d2afbSJilles Tjoelker  *   If thread is canceled, no socket is created.
114da7d2afbSJilles Tjoelker  */
1158495e8b1SKonstantin Belousov static int
__thr_accept4(int s,struct sockaddr * addr,socklen_t * addrlen,int flags)1168495e8b1SKonstantin Belousov __thr_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
117da7d2afbSJilles Tjoelker {
118da7d2afbSJilles Tjoelker 	struct pthread *curthread;
119da7d2afbSJilles Tjoelker 	int ret;
120da7d2afbSJilles Tjoelker 
121da7d2afbSJilles Tjoelker 	curthread = _get_curthread();
122da7d2afbSJilles Tjoelker 	_thr_cancel_enter(curthread);
123da7d2afbSJilles Tjoelker 	ret = __sys_accept4(s, addr, addrlen, flags);
124da7d2afbSJilles Tjoelker 	_thr_cancel_leave(curthread, ret == -1);
125da7d2afbSJilles Tjoelker 
126da7d2afbSJilles Tjoelker  	return (ret);
127da7d2afbSJilles Tjoelker }
128da7d2afbSJilles Tjoelker 
1298495e8b1SKonstantin Belousov static int
__thr_aio_suspend(const struct aiocb * const iocbs[],int niocb,const struct timespec * timeout)1308495e8b1SKonstantin Belousov __thr_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
131bb535300SJeff Roberson     timespec *timeout)
132bb535300SJeff Roberson {
1338495e8b1SKonstantin Belousov 	struct pthread *curthread;
134bb535300SJeff Roberson 	int ret;
135bb535300SJeff Roberson 
1368495e8b1SKonstantin Belousov 	curthread = _get_curthread();
137f08e1bf6SDavid Xu 	_thr_cancel_enter(curthread);
138bb535300SJeff Roberson 	ret = __sys_aio_suspend(iocbs, niocb, timeout);
13902c3c858SDavid Xu 	_thr_cancel_leave(curthread, 1);
140bb535300SJeff Roberson 
141a091d823SDavid Xu 	return (ret);
142bb535300SJeff Roberson }
143bb535300SJeff Roberson 
144635f917aSDavid Xu /*
145635f917aSDavid Xu  * Cancellation behavior:
146635f917aSDavid Xu  *   According to manual of close(), the file descriptor is always deleted.
147635f917aSDavid Xu  *   Here, thread is only canceled after the system call, so the file
148635f917aSDavid Xu  *   descriptor is always deleted despite whether the thread is canceled
149635f917aSDavid Xu  *   or not.
150635f917aSDavid Xu  */
1518495e8b1SKonstantin Belousov static int
__thr_close(int fd)1528495e8b1SKonstantin Belousov __thr_close(int fd)
153bb535300SJeff Roberson {
1548495e8b1SKonstantin Belousov 	struct pthread *curthread;
155bb535300SJeff Roberson 	int ret;
156bb535300SJeff Roberson 
1578495e8b1SKonstantin Belousov 	curthread = _get_curthread();
15802c3c858SDavid Xu 	_thr_cancel_enter2(curthread, 0);
159bb535300SJeff Roberson 	ret = __sys_close(fd);
16002c3c858SDavid Xu 	_thr_cancel_leave(curthread, 1);
161bb535300SJeff Roberson 
162a091d823SDavid Xu 	return (ret);
163bb535300SJeff Roberson }
164737afa3cSMike Makonnen 
165635f917aSDavid Xu /*
166635f917aSDavid Xu  * Cancellation behavior:
167635f917aSDavid Xu  *   If the thread is canceled, connection is not made.
168635f917aSDavid Xu  */
1698495e8b1SKonstantin Belousov static int
__thr_connect(int fd,const struct sockaddr * name,socklen_t namelen)1708495e8b1SKonstantin Belousov __thr_connect(int fd, const struct sockaddr *name, socklen_t namelen)
171737afa3cSMike Makonnen {
1728495e8b1SKonstantin Belousov 	struct pthread *curthread;
173737afa3cSMike Makonnen 	int ret;
174737afa3cSMike Makonnen 
1758495e8b1SKonstantin Belousov 	curthread = _get_curthread();
17602c3c858SDavid Xu 	_thr_cancel_enter(curthread);
177a091d823SDavid Xu 	ret = __sys_connect(fd, name, namelen);
17802c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
179a091d823SDavid Xu 
180a091d823SDavid Xu  	return (ret);
181737afa3cSMike Makonnen }
182737afa3cSMike Makonnen 
183635f917aSDavid Xu /*
184635f917aSDavid Xu  * Cancellation behavior:
185635f917aSDavid Xu  *   According to specification, only F_SETLKW is a cancellation point.
186635f917aSDavid Xu  *   Thread is only canceled at start, or canceled if the system call
187635f917aSDavid Xu  *   is failure, this means the function does not generate side effect
188635f917aSDavid Xu  *   if it is canceled.
189635f917aSDavid Xu  */
1908495e8b1SKonstantin Belousov static int
__thr_fcntl(int fd,int cmd,__intptr_t arg)191ec2b6b16SBrooks Davis __thr_fcntl(int fd, int cmd, __intptr_t arg)
192bb535300SJeff Roberson {
1938495e8b1SKonstantin Belousov 	struct pthread *curthread;
194bb535300SJeff Roberson 	int ret;
195bb535300SJeff Roberson 
1968495e8b1SKonstantin Belousov 	curthread = _get_curthread();
19702c3c858SDavid Xu 	if (cmd == F_OSETLKW || cmd == F_SETLKW) {
19802c3c858SDavid Xu 		_thr_cancel_enter(curthread);
199ec2b6b16SBrooks Davis 		ret = __sys_fcntl(fd, cmd, arg);
20002c3c858SDavid Xu 		_thr_cancel_leave(curthread, ret == -1);
20102c3c858SDavid Xu 	} else {
202ec2b6b16SBrooks Davis 		ret = __sys_fcntl(fd, cmd, arg);
203bb535300SJeff Roberson 	}
204bb535300SJeff Roberson 
205a091d823SDavid Xu 	return (ret);
206bb535300SJeff Roberson }
207bb535300SJeff Roberson 
208635f917aSDavid Xu /*
209635f917aSDavid Xu  * Cancellation behavior:
210635f917aSDavid Xu  *   Thread may be canceled after system call.
211635f917aSDavid Xu  */
2128495e8b1SKonstantin Belousov static int
__thr_fsync(int fd)2138495e8b1SKonstantin Belousov __thr_fsync(int fd)
21403d74100SMike Makonnen {
2158495e8b1SKonstantin Belousov 	struct pthread *curthread;
216bb535300SJeff Roberson 	int ret;
217bb535300SJeff Roberson 
2188495e8b1SKonstantin Belousov 	curthread = _get_curthread();
21902c3c858SDavid Xu 	_thr_cancel_enter2(curthread, 0);
220bb535300SJeff Roberson 	ret = __sys_fsync(fd);
22102c3c858SDavid Xu 	_thr_cancel_leave(curthread, 1);
222bb535300SJeff Roberson 
223a091d823SDavid Xu 	return (ret);
224bb535300SJeff Roberson }
225bb535300SJeff Roberson 
2261c1cc895SKonstantin Belousov static int
__thr_fdatasync(int fd)2271c1cc895SKonstantin Belousov __thr_fdatasync(int fd)
2281c1cc895SKonstantin Belousov {
2291c1cc895SKonstantin Belousov 	struct pthread *curthread;
2301c1cc895SKonstantin Belousov 	int ret;
2311c1cc895SKonstantin Belousov 
2321c1cc895SKonstantin Belousov 	curthread = _get_curthread();
2331c1cc895SKonstantin Belousov 	_thr_cancel_enter2(curthread, 0);
2341c1cc895SKonstantin Belousov 	ret = __sys_fdatasync(fd);
2351c1cc895SKonstantin Belousov 	_thr_cancel_leave(curthread, 1);
2361c1cc895SKonstantin Belousov 
2371c1cc895SKonstantin Belousov 	return (ret);
2381c1cc895SKonstantin Belousov }
2391c1cc895SKonstantin Belousov 
240635f917aSDavid Xu /*
241635f917aSDavid Xu  * Cancellation behavior:
242635f917aSDavid Xu  *   Thread may be canceled after system call.
243635f917aSDavid Xu  */
2448495e8b1SKonstantin Belousov static int
__thr_msync(void * addr,size_t len,int flags)2458495e8b1SKonstantin Belousov __thr_msync(void *addr, size_t len, int flags)
246737afa3cSMike Makonnen {
2478495e8b1SKonstantin Belousov 	struct pthread *curthread;
248737afa3cSMike Makonnen 	int ret;
249737afa3cSMike Makonnen 
2508495e8b1SKonstantin Belousov 	curthread = _get_curthread();
25102c3c858SDavid Xu 	_thr_cancel_enter2(curthread, 0);
252bb535300SJeff Roberson 	ret = __sys_msync(addr, len, flags);
25302c3c858SDavid Xu 	_thr_cancel_leave(curthread, 1);
254bb535300SJeff Roberson 
2558495e8b1SKonstantin Belousov 	return (ret);
256bb535300SJeff Roberson }
257bb535300SJeff Roberson 
2588495e8b1SKonstantin Belousov static int
__thr_clock_nanosleep(clockid_t clock_id,int flags,const struct timespec * time_to_sleep,struct timespec * time_remaining)2593f8455b0SEric van Gyzen __thr_clock_nanosleep(clockid_t clock_id, int flags,
2603f8455b0SEric van Gyzen     const struct timespec *time_to_sleep, struct timespec *time_remaining)
2613f8455b0SEric van Gyzen {
2623f8455b0SEric van Gyzen 	struct pthread *curthread;
2633f8455b0SEric van Gyzen 	int ret;
2643f8455b0SEric van Gyzen 
2653f8455b0SEric van Gyzen 	curthread = _get_curthread();
2663f8455b0SEric van Gyzen 	_thr_cancel_enter(curthread);
2673f8455b0SEric van Gyzen 	ret = __sys_clock_nanosleep(clock_id, flags, time_to_sleep,
2683f8455b0SEric van Gyzen 	    time_remaining);
2693f8455b0SEric van Gyzen 	_thr_cancel_leave(curthread, 1);
2703f8455b0SEric van Gyzen 
2713f8455b0SEric van Gyzen 	return (ret);
2723f8455b0SEric van Gyzen }
2733f8455b0SEric van Gyzen 
2743f8455b0SEric van Gyzen static int
__thr_nanosleep(const struct timespec * time_to_sleep,struct timespec * time_remaining)2758495e8b1SKonstantin Belousov __thr_nanosleep(const struct timespec *time_to_sleep,
276a091d823SDavid Xu     struct timespec *time_remaining)
277bb535300SJeff Roberson {
2788495e8b1SKonstantin Belousov 	struct pthread *curthread;
279bb535300SJeff Roberson 	int ret;
280bb535300SJeff Roberson 
2818495e8b1SKonstantin Belousov 	curthread = _get_curthread();
282f08e1bf6SDavid Xu 	_thr_cancel_enter(curthread);
283bb535300SJeff Roberson 	ret = __sys_nanosleep(time_to_sleep, time_remaining);
28402c3c858SDavid Xu 	_thr_cancel_leave(curthread, 1);
285bb535300SJeff Roberson 
286a091d823SDavid Xu 	return (ret);
287bb535300SJeff Roberson }
288bb535300SJeff Roberson 
289635f917aSDavid Xu /*
290635f917aSDavid Xu  * Cancellation behavior:
291635f917aSDavid Xu  *   If the thread is canceled, file is not opened.
292635f917aSDavid Xu  */
2938495e8b1SKonstantin Belousov static int
__thr_openat(int fd,const char * path,int flags,int mode)294ec2b6b16SBrooks Davis __thr_openat(int fd, const char *path, int flags, int mode)
29529670497SJilles Tjoelker {
2968495e8b1SKonstantin Belousov 	struct pthread *curthread;
297ec2b6b16SBrooks Davis 	int ret;
29829670497SJilles Tjoelker 
2998495e8b1SKonstantin Belousov 	curthread = _get_curthread();
30002c3c858SDavid Xu 	_thr_cancel_enter(curthread);
30129670497SJilles Tjoelker 	ret = __sys_openat(fd, path, flags, mode);
30202c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
30329670497SJilles Tjoelker 
3048495e8b1SKonstantin Belousov 	return (ret);
30529670497SJilles Tjoelker }
30629670497SJilles Tjoelker 
307635f917aSDavid Xu /*
308635f917aSDavid Xu  * Cancellation behavior:
309635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call returns something,
310635f917aSDavid Xu  *   the thread is not canceled.
311635f917aSDavid Xu  */
3128495e8b1SKonstantin Belousov static int
__thr_poll(struct pollfd * fds,unsigned int nfds,int timeout)3138495e8b1SKonstantin Belousov __thr_poll(struct pollfd *fds, unsigned int nfds, int timeout)
314bb535300SJeff Roberson {
3158495e8b1SKonstantin Belousov 	struct pthread *curthread;
316bb535300SJeff Roberson 	int ret;
317bb535300SJeff Roberson 
3188495e8b1SKonstantin Belousov 	curthread = _get_curthread();
31902c3c858SDavid Xu 	_thr_cancel_enter(curthread);
320a091d823SDavid Xu 	ret = __sys_poll(fds, nfds, timeout);
32102c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
322bb535300SJeff Roberson 
3238495e8b1SKonstantin Belousov 	return (ret);
324bb535300SJeff Roberson }
325737afa3cSMike Makonnen 
326635f917aSDavid Xu /*
327635f917aSDavid Xu  * Cancellation behavior:
328635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call returns something,
329635f917aSDavid Xu  *   the thread is not canceled.
330635f917aSDavid Xu  */
3318495e8b1SKonstantin Belousov static int
__thr_ppoll(struct pollfd pfd[],nfds_t nfds,const struct timespec * timeout,const sigset_t * newsigmask)3323d0045bbSKonstantin Belousov __thr_ppoll(struct pollfd pfd[], nfds_t nfds, const struct timespec *
3333d0045bbSKonstantin Belousov     timeout, const sigset_t *newsigmask)
3343d0045bbSKonstantin Belousov {
3353d0045bbSKonstantin Belousov 	struct pthread *curthread;
3363d0045bbSKonstantin Belousov 	int ret;
3373d0045bbSKonstantin Belousov 
3383d0045bbSKonstantin Belousov 	curthread = _get_curthread();
3393d0045bbSKonstantin Belousov 	_thr_cancel_enter(curthread);
3403d0045bbSKonstantin Belousov 	ret = __sys_ppoll(pfd, nfds, timeout, newsigmask);
3413d0045bbSKonstantin Belousov 	_thr_cancel_leave(curthread, ret == -1);
3423d0045bbSKonstantin Belousov 
3433d0045bbSKonstantin Belousov 	return (ret);
3443d0045bbSKonstantin Belousov }
3453d0045bbSKonstantin Belousov 
3463d0045bbSKonstantin Belousov /*
3473d0045bbSKonstantin Belousov  * Cancellation behavior:
3483d0045bbSKonstantin Belousov  *   Thread may be canceled at start, but if the system call returns something,
3493d0045bbSKonstantin Belousov  *   the thread is not canceled.
3503d0045bbSKonstantin Belousov  */
3513d0045bbSKonstantin Belousov static int
__thr_pselect(int count,fd_set * rfds,fd_set * wfds,fd_set * efds,const struct timespec * timo,const sigset_t * mask)3528495e8b1SKonstantin Belousov __thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
353a091d823SDavid Xu 	const struct timespec *timo, const sigset_t *mask)
354737afa3cSMike Makonnen {
3558495e8b1SKonstantin Belousov 	struct pthread *curthread;
356a091d823SDavid Xu 	int ret;
357737afa3cSMike Makonnen 
3588495e8b1SKonstantin Belousov 	curthread = _get_curthread();
35902c3c858SDavid Xu 	_thr_cancel_enter(curthread);
360066d836bSKonstantin Belousov 	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
36102c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
362a091d823SDavid Xu 
363737afa3cSMike Makonnen 	return (ret);
364737afa3cSMike Makonnen }
365bb535300SJeff Roberson 
366b072e86dSKonstantin Belousov static int
__thr_kevent(int kq,const struct kevent * changelist,int nchanges,struct kevent * eventlist,int nevents,const struct timespec * timeout)367b072e86dSKonstantin Belousov __thr_kevent(int kq, const struct kevent *changelist, int nchanges,
368b072e86dSKonstantin Belousov     struct kevent *eventlist, int nevents, const struct timespec *timeout)
369b072e86dSKonstantin Belousov {
370b072e86dSKonstantin Belousov 	struct pthread *curthread;
371b072e86dSKonstantin Belousov 	int ret;
372b072e86dSKonstantin Belousov 
373b072e86dSKonstantin Belousov 	if (nevents == 0) {
374b072e86dSKonstantin Belousov 		/*
375b072e86dSKonstantin Belousov 		 * No blocking, do not make the call cancellable.
376b072e86dSKonstantin Belousov 		 */
377b072e86dSKonstantin Belousov 		return (__sys_kevent(kq, changelist, nchanges, eventlist,
378b072e86dSKonstantin Belousov 		    nevents, timeout));
379b072e86dSKonstantin Belousov 	}
380b072e86dSKonstantin Belousov 	curthread = _get_curthread();
381b072e86dSKonstantin Belousov 	_thr_cancel_enter(curthread);
382b072e86dSKonstantin Belousov 	ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
383b072e86dSKonstantin Belousov 	    timeout);
384b072e86dSKonstantin Belousov 	_thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
385b072e86dSKonstantin Belousov 
386b072e86dSKonstantin Belousov 	return (ret);
387b072e86dSKonstantin Belousov }
388b072e86dSKonstantin Belousov 
389635f917aSDavid Xu /*
390635f917aSDavid Xu  * Cancellation behavior:
391635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call got some data,
392635f917aSDavid Xu  *   the thread is not canceled.
393635f917aSDavid Xu  */
3948495e8b1SKonstantin Belousov static ssize_t
__thr_read(int fd,void * buf,size_t nbytes)3958495e8b1SKonstantin Belousov __thr_read(int fd, void *buf, size_t nbytes)
396a091d823SDavid Xu {
3978495e8b1SKonstantin Belousov 	struct pthread *curthread;
398a091d823SDavid Xu 	ssize_t	ret;
399a091d823SDavid Xu 
4008495e8b1SKonstantin Belousov 	curthread = _get_curthread();
40102c3c858SDavid Xu 	_thr_cancel_enter(curthread);
402a091d823SDavid Xu 	ret = __sys_read(fd, buf, nbytes);
40302c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
404a091d823SDavid Xu 
4058495e8b1SKonstantin Belousov 	return (ret);
406a091d823SDavid Xu }
407a091d823SDavid Xu 
408635f917aSDavid Xu /*
409635f917aSDavid Xu  * Cancellation behavior:
410635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call got some data,
411635f917aSDavid Xu  *   the thread is not canceled.
412635f917aSDavid Xu  */
4138495e8b1SKonstantin Belousov static ssize_t
__thr_readv(int fd,const struct iovec * iov,int iovcnt)4148495e8b1SKonstantin Belousov __thr_readv(int fd, const struct iovec *iov, int iovcnt)
415a091d823SDavid Xu {
4168495e8b1SKonstantin Belousov 	struct pthread *curthread;
417a091d823SDavid Xu 	ssize_t ret;
418a091d823SDavid Xu 
4198495e8b1SKonstantin Belousov 	curthread = _get_curthread();
42002c3c858SDavid Xu 	_thr_cancel_enter(curthread);
421a091d823SDavid Xu 	ret = __sys_readv(fd, iov, iovcnt);
42202c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
4238495e8b1SKonstantin Belousov 	return (ret);
424a091d823SDavid Xu }
425a091d823SDavid Xu 
426635f917aSDavid Xu /*
427635f917aSDavid Xu  * Cancellation behavior:
428635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call got some data,
429635f917aSDavid Xu  *   the thread is not canceled.
430635f917aSDavid Xu  */
4318495e8b1SKonstantin Belousov static ssize_t
__thr_recvfrom(int s,void * b,size_t l,int f,struct sockaddr * from,socklen_t * fl)4328495e8b1SKonstantin Belousov __thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
433737afa3cSMike Makonnen     socklen_t *fl)
434737afa3cSMike Makonnen {
4358495e8b1SKonstantin Belousov 	struct pthread *curthread;
436737afa3cSMike Makonnen 	ssize_t ret;
437737afa3cSMike Makonnen 
4388495e8b1SKonstantin Belousov 	curthread = _get_curthread();
43902c3c858SDavid Xu 	_thr_cancel_enter(curthread);
440737afa3cSMike Makonnen 	ret = __sys_recvfrom(s, b, l, f, from, fl);
44102c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
442737afa3cSMike Makonnen 	return (ret);
443737afa3cSMike Makonnen }
444737afa3cSMike Makonnen 
445635f917aSDavid Xu /*
446635f917aSDavid Xu  * Cancellation behavior:
447635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call got some data,
448635f917aSDavid Xu  *   the thread is not canceled.
449635f917aSDavid Xu  */
4508495e8b1SKonstantin Belousov static ssize_t
__thr_recvmsg(int s,struct msghdr * m,int f)4518495e8b1SKonstantin Belousov __thr_recvmsg(int s, struct msghdr *m, int f)
452737afa3cSMike Makonnen {
4538495e8b1SKonstantin Belousov 	struct pthread *curthread;
454737afa3cSMike Makonnen 	ssize_t ret;
455737afa3cSMike Makonnen 
4568495e8b1SKonstantin Belousov 	curthread = _get_curthread();
45702c3c858SDavid Xu 	_thr_cancel_enter(curthread);
458737afa3cSMike Makonnen 	ret = __sys_recvmsg(s, m, f);
45902c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
460737afa3cSMike Makonnen 	return (ret);
461737afa3cSMike Makonnen }
462737afa3cSMike Makonnen 
463635f917aSDavid Xu /*
464635f917aSDavid Xu  * Cancellation behavior:
465635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call returns something,
466635f917aSDavid Xu  *   the thread is not canceled.
467635f917aSDavid Xu  */
4688495e8b1SKonstantin Belousov static int
__thr_select(int numfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)4698495e8b1SKonstantin Belousov __thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
470bb535300SJeff Roberson 	struct timeval *timeout)
471bb535300SJeff Roberson {
4728495e8b1SKonstantin Belousov 	struct pthread *curthread;
473bb535300SJeff Roberson 	int ret;
474bb535300SJeff Roberson 
4758495e8b1SKonstantin Belousov 	curthread = _get_curthread();
47602c3c858SDavid Xu 	_thr_cancel_enter(curthread);
477bb535300SJeff Roberson 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
47802c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
4798495e8b1SKonstantin Belousov 	return (ret);
480bb535300SJeff Roberson }
481bb535300SJeff Roberson 
482635f917aSDavid Xu /*
483635f917aSDavid Xu  * Cancellation behavior:
484635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call sent
485635f917aSDavid Xu  *   data, the thread is not canceled.
486635f917aSDavid Xu  */
4878495e8b1SKonstantin Belousov static ssize_t
__thr_sendmsg(int s,const struct msghdr * m,int f)4888495e8b1SKonstantin Belousov __thr_sendmsg(int s, const struct msghdr *m, int f)
489737afa3cSMike Makonnen {
4908495e8b1SKonstantin Belousov 	struct pthread *curthread;
491737afa3cSMike Makonnen 	ssize_t ret;
492737afa3cSMike Makonnen 
4938495e8b1SKonstantin Belousov 	curthread = _get_curthread();
49402c3c858SDavid Xu 	_thr_cancel_enter(curthread);
495737afa3cSMike Makonnen 	ret = __sys_sendmsg(s, m, f);
49602c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret <= 0);
497737afa3cSMike Makonnen 	return (ret);
498737afa3cSMike Makonnen }
499737afa3cSMike Makonnen 
500635f917aSDavid Xu /*
501635f917aSDavid Xu  * Cancellation behavior:
502635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call sent some
503635f917aSDavid Xu  *   data, the thread is not canceled.
504635f917aSDavid Xu  */
5058495e8b1SKonstantin Belousov static ssize_t
__thr_sendto(int s,const void * m,size_t l,int f,const struct sockaddr * t,socklen_t tl)5068495e8b1SKonstantin Belousov __thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
507737afa3cSMike Makonnen     socklen_t tl)
508737afa3cSMike Makonnen {
5098495e8b1SKonstantin Belousov 	struct pthread *curthread;
510737afa3cSMike Makonnen 	ssize_t ret;
511737afa3cSMike Makonnen 
5128495e8b1SKonstantin Belousov 	curthread = _get_curthread();
51302c3c858SDavid Xu 	_thr_cancel_enter(curthread);
514737afa3cSMike Makonnen 	ret = __sys_sendto(s, m, l, f, t, tl);
51502c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret <= 0);
516737afa3cSMike Makonnen 	return (ret);
517737afa3cSMike Makonnen }
518737afa3cSMike Makonnen 
5198495e8b1SKonstantin Belousov static int
__thr_system(const char * string)5208495e8b1SKonstantin Belousov __thr_system(const char *string)
521bb535300SJeff Roberson {
5228495e8b1SKonstantin Belousov 	struct pthread *curthread;
523bb535300SJeff Roberson 	int ret;
524bb535300SJeff Roberson 
5258495e8b1SKonstantin Belousov 	curthread = _get_curthread();
526f08e1bf6SDavid Xu 	_thr_cancel_enter(curthread);
5278495e8b1SKonstantin Belousov 	ret = __libc_system(string);
52802c3c858SDavid Xu 	_thr_cancel_leave(curthread, 1);
5298495e8b1SKonstantin Belousov 	return (ret);
530bb535300SJeff Roberson }
531bb535300SJeff Roberson 
532635f917aSDavid Xu /*
533635f917aSDavid Xu  * Cancellation behavior:
534635f917aSDavid Xu  *   If thread is canceled, the system call is not completed,
535635f917aSDavid Xu  *   this means not all bytes were drained.
536635f917aSDavid Xu  */
5378495e8b1SKonstantin Belousov static int
__thr_tcdrain(int fd)5388495e8b1SKonstantin Belousov __thr_tcdrain(int fd)
539bb535300SJeff Roberson {
5408495e8b1SKonstantin Belousov 	struct pthread *curthread;
541bb535300SJeff Roberson 	int ret;
542bb535300SJeff Roberson 
5438495e8b1SKonstantin Belousov 	curthread = _get_curthread();
54402c3c858SDavid Xu 	_thr_cancel_enter(curthread);
5458495e8b1SKonstantin Belousov 	ret = __libc_tcdrain(fd);
54602c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret == -1);
547737afa3cSMike Makonnen 	return (ret);
548737afa3cSMike Makonnen }
549a091d823SDavid Xu 
550635f917aSDavid Xu /*
551635f917aSDavid Xu  * Cancellation behavior:
552635f917aSDavid Xu  *   Thread may be canceled at start, but if the system call returns
553635f917aSDavid Xu  *   a child pid, the thread is not canceled.
554635f917aSDavid Xu  */
5558495e8b1SKonstantin Belousov static pid_t
__thr_wait4(pid_t pid,int * status,int options,struct rusage * rusage)5568495e8b1SKonstantin Belousov __thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
55705c3a5eaSDavid Xu {
5588495e8b1SKonstantin Belousov 	struct pthread *curthread;
55905c3a5eaSDavid Xu 	pid_t ret;
56005c3a5eaSDavid Xu 
5618495e8b1SKonstantin Belousov 	curthread = _get_curthread();
56202c3c858SDavid Xu 	_thr_cancel_enter(curthread);
56305c3a5eaSDavid Xu 	ret = __sys_wait4(pid, status, options, rusage);
56402c3c858SDavid Xu 	_thr_cancel_leave(curthread, ret <= 0);
5658495e8b1SKonstantin Belousov 	return (ret);
566bb535300SJeff Roberson }
567bb535300SJeff Roberson 
568635f917aSDavid Xu /*
569635f917aSDavid Xu  * Cancellation behavior:
5703d0045bbSKonstantin Belousov  *   Thread may be canceled at start, but if the system call returns
5713d0045bbSKonstantin Belousov  *   a child pid, the thread is not canceled.
5723d0045bbSKonstantin Belousov  */
5733d0045bbSKonstantin Belousov static pid_t
__thr_wait6(idtype_t idtype,id_t id,int * status,int options,struct __wrusage * ru,siginfo_t * infop)5743d0045bbSKonstantin Belousov __thr_wait6(idtype_t idtype, id_t id, int *status, int options,
5753d0045bbSKonstantin Belousov     struct __wrusage *ru, siginfo_t *infop)
5763d0045bbSKonstantin Belousov {
5773d0045bbSKonstantin Belousov 	struct pthread *curthread;
5783d0045bbSKonstantin Belousov 	pid_t ret;
5793d0045bbSKonstantin Belousov 
5803d0045bbSKonstantin Belousov 	curthread = _get_curthread();
5813d0045bbSKonstantin Belousov 	_thr_cancel_enter(curthread);
5823d0045bbSKonstantin Belousov 	ret = __sys_wait6(idtype, id, status, options, ru, infop);
5833d0045bbSKonstantin Belousov 	_thr_cancel_leave(curthread, ret <= 0);
5843d0045bbSKonstantin Belousov 	return (ret);
5853d0045bbSKonstantin Belousov }
5863d0045bbSKonstantin Belousov 
5873d0045bbSKonstantin Belousov /*
5883d0045bbSKonstantin Belousov  * Cancellation behavior:
589635f917aSDavid Xu  *   Thread may be canceled at start, but if the thread wrote some data,
590635f917aSDavid Xu  *   it is not canceled.
591635f917aSDavid Xu  */
5928495e8b1SKonstantin Belousov static ssize_t
__thr_write(int fd,const void * buf,size_t nbytes)5938495e8b1SKonstantin Belousov __thr_write(int fd, const void *buf, size_t nbytes)
594bb535300SJeff Roberson {
5958495e8b1SKonstantin Belousov 	struct pthread *curthread;
596bb535300SJeff Roberson 	ssize_t	ret;
597bb535300SJeff Roberson 
5988495e8b1SKonstantin Belousov 	curthread = _get_curthread();
59902c3c858SDavid Xu 	_thr_cancel_enter(curthread);
600bb535300SJeff Roberson 	ret = __sys_write(fd, buf, nbytes);
60102c3c858SDavid Xu 	_thr_cancel_leave(curthread, (ret <= 0));
6028495e8b1SKonstantin Belousov 	return (ret);
603bb535300SJeff Roberson }
604bb535300SJeff Roberson 
605635f917aSDavid Xu /*
606635f917aSDavid Xu  * Cancellation behavior:
607635f917aSDavid Xu  *   Thread may be canceled at start, but if the thread wrote some data,
608635f917aSDavid Xu  *   it is not canceled.
609635f917aSDavid Xu  */
6108495e8b1SKonstantin Belousov static ssize_t
__thr_writev(int fd,const struct iovec * iov,int iovcnt)6118495e8b1SKonstantin Belousov __thr_writev(int fd, const struct iovec *iov, int iovcnt)
612bb535300SJeff Roberson {
6138495e8b1SKonstantin Belousov 	struct pthread *curthread;
614bb535300SJeff Roberson 	ssize_t ret;
615bb535300SJeff Roberson 
6168495e8b1SKonstantin Belousov 	curthread = _get_curthread();
61702c3c858SDavid Xu 	_thr_cancel_enter(curthread);
618bb535300SJeff Roberson 	ret = __sys_writev(fd, iov, iovcnt);
61902c3c858SDavid Xu 	_thr_cancel_leave(curthread, (ret <= 0));
6208495e8b1SKonstantin Belousov 	return (ret);
6218495e8b1SKonstantin Belousov }
6228495e8b1SKonstantin Belousov 
623*a56fe703SKonstantin Belousov static int
__thr_uexterr_gettext(char * buf,size_t bufsz)624*a56fe703SKonstantin Belousov __thr_uexterr_gettext(char *buf, size_t bufsz)
625*a56fe703SKonstantin Belousov {
626*a56fe703SKonstantin Belousov 	struct pthread *curthread;
627*a56fe703SKonstantin Belousov 
628*a56fe703SKonstantin Belousov 	curthread = _get_curthread();
629*a56fe703SKonstantin Belousov 	return (__uexterr_format(&curthread->uexterr, buf, bufsz));
630*a56fe703SKonstantin Belousov }
631*a56fe703SKonstantin Belousov 
6328495e8b1SKonstantin Belousov void
__thr_interpose_libc(void)6338495e8b1SKonstantin Belousov __thr_interpose_libc(void)
6348495e8b1SKonstantin Belousov {
6358495e8b1SKonstantin Belousov 
6361a744fefSKonstantin Belousov 	__set_error_selector(__error_threaded);
6378495e8b1SKonstantin Belousov #define	SLOT(name)					\
6388495e8b1SKonstantin Belousov 	*(__libc_interposing_slot(INTERPOS_##name)) =	\
6398495e8b1SKonstantin Belousov 	    (interpos_func_t)__thr_##name;
6409cbd9658SBrooks Davis 	SLOT(system);
6419cbd9658SBrooks Davis 	SLOT(tcdrain);
6429cbd9658SBrooks Davis 	SLOT(spinlock);
6439cbd9658SBrooks Davis 	SLOT(spinunlock);
6449cbd9658SBrooks Davis 	SLOT(map_stacks_exec);
6459cbd9658SBrooks Davis #undef SLOT
6469cbd9658SBrooks Davis 
6479cbd9658SBrooks Davis #define	SLOT(name)					\
648672464f7SBrooks Davis 	*(__libc_interposing_slot(INTERPOS_##name)) =	\
6499cbd9658SBrooks Davis 	    (interpos_func_t)__thr_##name;
6508495e8b1SKonstantin Belousov 	SLOT(accept);
6518495e8b1SKonstantin Belousov 	SLOT(accept4);
6528495e8b1SKonstantin Belousov 	SLOT(aio_suspend);
6538495e8b1SKonstantin Belousov 	SLOT(close);
6548495e8b1SKonstantin Belousov 	SLOT(connect);
6558495e8b1SKonstantin Belousov 	SLOT(fcntl);
6568495e8b1SKonstantin Belousov 	SLOT(fsync);
6578495e8b1SKonstantin Belousov 	SLOT(fork);
6588495e8b1SKonstantin Belousov 	SLOT(msync);
6598495e8b1SKonstantin Belousov 	SLOT(nanosleep);
6608495e8b1SKonstantin Belousov 	SLOT(openat);
6618495e8b1SKonstantin Belousov 	SLOT(poll);
6628495e8b1SKonstantin Belousov 	SLOT(pselect);
6638495e8b1SKonstantin Belousov 	SLOT(read);
6648495e8b1SKonstantin Belousov 	SLOT(readv);
6658495e8b1SKonstantin Belousov 	SLOT(recvfrom);
6668495e8b1SKonstantin Belousov 	SLOT(recvmsg);
6678495e8b1SKonstantin Belousov 	SLOT(select);
6688495e8b1SKonstantin Belousov 	SLOT(sendmsg);
6698495e8b1SKonstantin Belousov 	SLOT(sendto);
6708495e8b1SKonstantin Belousov 	SLOT(setcontext);
6718495e8b1SKonstantin Belousov 	SLOT(sigaction);
6728495e8b1SKonstantin Belousov 	SLOT(sigprocmask);
6738495e8b1SKonstantin Belousov 	SLOT(sigsuspend);
6748495e8b1SKonstantin Belousov 	SLOT(sigwait);
6758495e8b1SKonstantin Belousov 	SLOT(sigtimedwait);
6768495e8b1SKonstantin Belousov 	SLOT(sigwaitinfo);
6778495e8b1SKonstantin Belousov 	SLOT(swapcontext);
6788495e8b1SKonstantin Belousov 	SLOT(wait4);
6798495e8b1SKonstantin Belousov 	SLOT(write);
6808495e8b1SKonstantin Belousov 	SLOT(writev);
681b072e86dSKonstantin Belousov 	SLOT(kevent);
6823d0045bbSKonstantin Belousov 	SLOT(wait6);
6833d0045bbSKonstantin Belousov 	SLOT(ppoll);
6841c1cc895SKonstantin Belousov 	SLOT(fdatasync);
6853f8455b0SEric van Gyzen 	SLOT(clock_nanosleep);
68621f749daSKonstantin Belousov 	SLOT(pdfork);
687*a56fe703SKonstantin Belousov 	SLOT(uexterr_gettext);
6888495e8b1SKonstantin Belousov #undef SLOT
6898495e8b1SKonstantin Belousov 	*(__libc_interposing_slot(
6908495e8b1SKonstantin Belousov 	    INTERPOS__pthread_mutex_init_calloc_cb)) =
6918495e8b1SKonstantin Belousov 	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
692bb535300SJeff Roberson }
693