1112918Sjeff/*
2277317Skib * Copyright (c) 2014 The FreeBSD Foundation.
3144518Sdavidxu * Copyright (C) 2005 David Xu <davidxu@freebsd.org>.
4144518Sdavidxu * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>.
5144518Sdavidxu * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
6112918Sjeff * All rights reserved.
7112918Sjeff *
8277317Skib * Portions of this software were developed by Konstantin Belousov
9277317Skib * under sponsorship from the FreeBSD Foundation.
10277317Skib *
11112918Sjeff * Redistribution and use in source and binary forms, with or without
12112918Sjeff * modification, are permitted provided that the following conditions
13112918Sjeff * are met:
14112918Sjeff * 1. Redistributions of source code must retain the above copyright
15112918Sjeff *    notice(s), this list of conditions and the following disclaimer as
16112918Sjeff *    the first lines of this file unmodified other than the possible
17112918Sjeff *    addition of one or more copyright notices.
18112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright
19112918Sjeff *    notice(s), this list of conditions and the following disclaimer in
20112918Sjeff *    the documentation and/or other materials provided with the
21112918Sjeff *    distribution.
22112918Sjeff *
23112918Sjeff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
24112918Sjeff * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26112918Sjeff * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
27112918Sjeff * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28112918Sjeff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29112918Sjeff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30112918Sjeff * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31112918Sjeff * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32112918Sjeff * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33112918Sjeff * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34112918Sjeff */
35112918Sjeff
36112918Sjeff/*
37112918Sjeff * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
38112918Sjeff * All rights reserved.
39112918Sjeff *
40112918Sjeff * Redistribution and use in source and binary forms, with or without
41112918Sjeff * modification, are permitted provided that the following conditions
42112918Sjeff * are met:
43112918Sjeff * 1. Redistributions of source code must retain the above copyright
44112918Sjeff *    notice, this list of conditions and the following disclaimer.
45112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright
46112918Sjeff *    notice, this list of conditions and the following disclaimer in the
47112918Sjeff *    documentation and/or other materials provided with the distribution.
48165967Simp * 3. Neither the name of the author nor the names of any co-contributors
49112918Sjeff *    may be used to endorse or promote products derived from this software
50112918Sjeff *    without specific prior written permission.
51112918Sjeff *
52112918Sjeff * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
53112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55112918Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62112918Sjeff * SUCH DAMAGE.
63112918Sjeff *
64112918Sjeff */
65112918Sjeff
66277317Skib#include <sys/cdefs.h>
67277317Skib__FBSDID("$FreeBSD$");
68277317Skib
69157457Sdavidxu#include "namespace.h"
70144518Sdavidxu#include <sys/types.h>
71112918Sjeff#include <sys/mman.h>
72112918Sjeff#include <sys/param.h>
73112918Sjeff#include <sys/select.h>
74144518Sdavidxu#include <sys/signalvar.h>
75135301Smtm#include <sys/socket.h>
76144518Sdavidxu#include <sys/stat.h>
77112918Sjeff#include <sys/time.h>
78112918Sjeff#include <sys/uio.h>
79112918Sjeff#include <sys/wait.h>
80112918Sjeff#include <aio.h>
81112918Sjeff#include <dirent.h>
82112918Sjeff#include <errno.h>
83112918Sjeff#include <fcntl.h>
84112918Sjeff#include <poll.h>
85112918Sjeff#include <signal.h>
86112918Sjeff#include <stdarg.h>
87112918Sjeff#include <stdio.h>
88112918Sjeff#include <stdlib.h>
89112918Sjeff#include <string.h>
90112918Sjeff#include <termios.h>
91112918Sjeff#include <unistd.h>
92144518Sdavidxu#include <pthread.h>
93157457Sdavidxu#include "un-namespace.h"
94112918Sjeff
95277317Skib#include "libc_private.h"
96112918Sjeff#include "thr_private.h"
97112918Sjeff
98189549Sdavidxu#ifdef SYSCALL_COMPAT
99277317Skibextern int __fcntl_compat(int, int, ...);
100189549Sdavidxu#endif
101157457Sdavidxu
102277317Skibstatic int
103277317Skib__thr_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
104135301Smtm{
105144518Sdavidxu	struct pthread *curthread;
106135301Smtm	int ret;
107135301Smtm
108144518Sdavidxu	curthread = _get_curthread();
109212076Sdavidxu	_thr_cancel_enter(curthread);
110135301Smtm	ret = __sys_accept(s, addr, addrlen);
111212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
112144518Sdavidxu
113144518Sdavidxu 	return (ret);
114135301Smtm}
115135301Smtm
116250154Sjilles/*
117250154Sjilles * Cancellation behavior:
118250154Sjilles *   If thread is canceled, no socket is created.
119250154Sjilles */
120277317Skibstatic int
121277317Skib__thr_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
122250154Sjilles{
123250154Sjilles	struct pthread *curthread;
124250154Sjilles	int ret;
125250154Sjilles
126250154Sjilles	curthread = _get_curthread();
127250154Sjilles	_thr_cancel_enter(curthread);
128250154Sjilles	ret = __sys_accept4(s, addr, addrlen, flags);
129250154Sjilles	_thr_cancel_leave(curthread, ret == -1);
130250154Sjilles
131250154Sjilles 	return (ret);
132250154Sjilles}
133250154Sjilles
134277317Skibstatic int
135277317Skib__thr_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
136112918Sjeff    timespec *timeout)
137112918Sjeff{
138277317Skib	struct pthread *curthread;
139144518Sdavidxu	int ret;
140112918Sjeff
141277317Skib	curthread = _get_curthread();
142164583Sdavidxu	_thr_cancel_enter(curthread);
143112918Sjeff	ret = __sys_aio_suspend(iocbs, niocb, timeout);
144212076Sdavidxu	_thr_cancel_leave(curthread, 1);
145112918Sjeff
146144518Sdavidxu	return (ret);
147112918Sjeff}
148112918Sjeff
149211524Sdavidxu/*
150211524Sdavidxu * Cancellation behavior:
151211524Sdavidxu *   According to manual of close(), the file descriptor is always deleted.
152211524Sdavidxu *   Here, thread is only canceled after the system call, so the file
153211524Sdavidxu *   descriptor is always deleted despite whether the thread is canceled
154211524Sdavidxu *   or not.
155211524Sdavidxu */
156277317Skibstatic int
157277317Skib__thr_close(int fd)
158112918Sjeff{
159277317Skib	struct pthread *curthread;
160277317Skib	int ret;
161112918Sjeff
162277317Skib	curthread = _get_curthread();
163212076Sdavidxu	_thr_cancel_enter2(curthread, 0);
164112918Sjeff	ret = __sys_close(fd);
165212076Sdavidxu	_thr_cancel_leave(curthread, 1);
166112918Sjeff
167144518Sdavidxu	return (ret);
168112918Sjeff}
169135301Smtm
170211524Sdavidxu/*
171211524Sdavidxu * Cancellation behavior:
172211524Sdavidxu *   If the thread is canceled, connection is not made.
173211524Sdavidxu */
174277317Skibstatic int
175277317Skib__thr_connect(int fd, const struct sockaddr *name, socklen_t namelen)
176135301Smtm{
177277317Skib	struct pthread *curthread;
178135301Smtm	int ret;
179135301Smtm
180277317Skib	curthread = _get_curthread();
181212076Sdavidxu	_thr_cancel_enter(curthread);
182144518Sdavidxu	ret = __sys_connect(fd, name, namelen);
183212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
184144518Sdavidxu
185144518Sdavidxu 	return (ret);
186135301Smtm}
187112918Sjeff
188211524Sdavidxu/*
189211524Sdavidxu * Cancellation behavior:
190211524Sdavidxu *   According to specification, only F_SETLKW is a cancellation point.
191211524Sdavidxu *   Thread is only canceled at start, or canceled if the system call
192211524Sdavidxu *   is failure, this means the function does not generate side effect
193211524Sdavidxu *   if it is canceled.
194211524Sdavidxu */
195277317Skibstatic int
196277317Skib__thr_fcntl(int fd, int cmd, ...)
197112918Sjeff{
198277317Skib	struct pthread *curthread;
199277317Skib	int ret;
200112918Sjeff	va_list	ap;
201211524Sdavidxu
202277317Skib	curthread = _get_curthread();
203112918Sjeff	va_start(ap, cmd);
204212076Sdavidxu	if (cmd == F_OSETLKW || cmd == F_SETLKW) {
205212076Sdavidxu		_thr_cancel_enter(curthread);
206211522Sdavidxu#ifdef SYSCALL_COMPAT
207211522Sdavidxu		ret = __fcntl_compat(fd, cmd, va_arg(ap, void *));
208211522Sdavidxu#else
209211522Sdavidxu		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
210211522Sdavidxu#endif
211212076Sdavidxu		_thr_cancel_leave(curthread, ret == -1);
212212076Sdavidxu	} else {
213189549Sdavidxu#ifdef SYSCALL_COMPAT
214179434Sdfr		ret = __fcntl_compat(fd, cmd, va_arg(ap, void *));
215189549Sdavidxu#else
216189553Sdavidxu		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
217189549Sdavidxu#endif
218112918Sjeff	}
219112918Sjeff	va_end(ap);
220112918Sjeff
221144518Sdavidxu	return (ret);
222112918Sjeff}
223112918Sjeff
224211524Sdavidxu/*
225211524Sdavidxu * Cancellation behavior:
226211524Sdavidxu *   Thread may be canceled after system call.
227211524Sdavidxu */
228277317Skibstatic int
229277317Skib__thr_fsync(int fd)
230131181Smtm{
231277317Skib	struct pthread *curthread;
232277317Skib	int ret;
233131181Smtm
234277317Skib	curthread = _get_curthread();
235212076Sdavidxu	_thr_cancel_enter2(curthread, 0);
236112918Sjeff	ret = __sys_fsync(fd);
237212076Sdavidxu	_thr_cancel_leave(curthread, 1);
238112918Sjeff
239144518Sdavidxu	return (ret);
240112918Sjeff}
241112918Sjeff
242211524Sdavidxu/*
243211524Sdavidxu * Cancellation behavior:
244211524Sdavidxu *   Thread may be canceled after system call.
245211524Sdavidxu */
246277317Skibstatic int
247277317Skib__thr_msync(void *addr, size_t len, int flags)
248135301Smtm{
249277317Skib	struct pthread *curthread;
250277317Skib	int ret;
251112918Sjeff
252277317Skib	curthread = _get_curthread();
253212076Sdavidxu	_thr_cancel_enter2(curthread, 0);
254112918Sjeff	ret = __sys_msync(addr, len, flags);
255212076Sdavidxu	_thr_cancel_leave(curthread, 1);
256112918Sjeff
257277317Skib	return (ret);
258112918Sjeff}
259112918Sjeff
260277317Skibstatic int
261277317Skib__thr_nanosleep(const struct timespec *time_to_sleep,
262144518Sdavidxu    struct timespec *time_remaining)
263112918Sjeff{
264277317Skib	struct pthread *curthread;
265277317Skib	int ret;
266112918Sjeff
267277317Skib	curthread = _get_curthread();
268164583Sdavidxu	_thr_cancel_enter(curthread);
269112918Sjeff	ret = __sys_nanosleep(time_to_sleep, time_remaining);
270212076Sdavidxu	_thr_cancel_leave(curthread, 1);
271112918Sjeff
272144518Sdavidxu	return (ret);
273112918Sjeff}
274112918Sjeff
275211524Sdavidxu/*
276211524Sdavidxu * Cancellation behavior:
277211524Sdavidxu *   If the thread is canceled, file is not opened.
278211524Sdavidxu */
279277317Skibstatic int
280277317Skib__thr_openat(int fd, const char *path, int flags, ...)
281112918Sjeff{
282277317Skib	struct pthread *curthread;
283277317Skib	int mode, ret;
284112918Sjeff	va_list	ap;
285112918Sjeff
286112918Sjeff
287197968Sjilles	/* Check if the file is being created: */
288277317Skib	if ((flags & O_CREAT) != 0) {
289197968Sjilles		/* Get the creation mode: */
290197968Sjilles		va_start(ap, flags);
291197968Sjilles		mode = va_arg(ap, int);
292197968Sjilles		va_end(ap);
293277317Skib	} else {
294277317Skib		mode = 0;
295197968Sjilles	}
296197968Sjilles
297277317Skib	curthread = _get_curthread();
298212076Sdavidxu	_thr_cancel_enter(curthread);
299197968Sjilles	ret = __sys_openat(fd, path, flags, mode);
300212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
301197968Sjilles
302277317Skib	return (ret);
303197968Sjilles}
304197968Sjilles
305211524Sdavidxu/*
306211524Sdavidxu * Cancellation behavior:
307211524Sdavidxu *   Thread may be canceled at start, but if the system call returns something,
308211524Sdavidxu *   the thread is not canceled.
309211524Sdavidxu */
310277317Skibstatic int
311277317Skib__thr_poll(struct pollfd *fds, unsigned int nfds, int timeout)
312112918Sjeff{
313277317Skib	struct pthread *curthread;
314112918Sjeff	int ret;
315112918Sjeff
316277317Skib	curthread = _get_curthread();
317212076Sdavidxu	_thr_cancel_enter(curthread);
318112918Sjeff	ret = __sys_poll(fds, nfds, timeout);
319212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
320112918Sjeff
321277317Skib	return (ret);
322112918Sjeff}
323112918Sjeff
324211524Sdavidxu/*
325211524Sdavidxu * Cancellation behavior:
326211524Sdavidxu *   Thread may be canceled at start, but if the system call returns something,
327211524Sdavidxu *   the thread is not canceled.
328211524Sdavidxu */
329277317Skibstatic int
330281981Skib__thr_ppoll(struct pollfd pfd[], nfds_t nfds, const struct timespec *
331281981Skib    timeout, const sigset_t *newsigmask)
332281981Skib{
333281981Skib	struct pthread *curthread;
334281981Skib	int ret;
335281981Skib
336281981Skib	curthread = _get_curthread();
337281981Skib	_thr_cancel_enter(curthread);
338281981Skib	ret = __sys_ppoll(pfd, nfds, timeout, newsigmask);
339281981Skib	_thr_cancel_leave(curthread, ret == -1);
340281981Skib
341281981Skib	return (ret);
342281981Skib}
343281981Skib
344281981Skib/*
345281981Skib * Cancellation behavior:
346281981Skib *   Thread may be canceled at start, but if the system call returns something,
347281981Skib *   the thread is not canceled.
348281981Skib */
349281981Skibstatic int
350277317Skib__thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
351112918Sjeff	const struct timespec *timo, const sigset_t *mask)
352112918Sjeff{
353277317Skib	struct pthread *curthread;
354112918Sjeff	int ret;
355112918Sjeff
356277317Skib	curthread = _get_curthread();
357212076Sdavidxu	_thr_cancel_enter(curthread);
358198508Skib	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
359212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
360112918Sjeff
361112918Sjeff	return (ret);
362112918Sjeff}
363112918Sjeff
364281454Skibstatic int
365281454Skib__thr_kevent(int kq, const struct kevent *changelist, int nchanges,
366281454Skib    struct kevent *eventlist, int nevents, const struct timespec *timeout)
367281454Skib{
368281454Skib	struct pthread *curthread;
369281454Skib	int ret;
370281454Skib
371281454Skib	if (nevents == 0) {
372281454Skib		/*
373281454Skib		 * No blocking, do not make the call cancellable.
374281454Skib		 */
375281454Skib		return (__sys_kevent(kq, changelist, nchanges, eventlist,
376281454Skib		    nevents, timeout));
377281454Skib	}
378281454Skib	curthread = _get_curthread();
379281454Skib	_thr_cancel_enter(curthread);
380281454Skib	ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
381281454Skib	    timeout);
382281454Skib	_thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
383281454Skib
384281454Skib	return (ret);
385281454Skib}
386281454Skib
387211524Sdavidxu/*
388211524Sdavidxu * Cancellation behavior:
389211524Sdavidxu *   Thread may be canceled at start, but if the system call got some data,
390211524Sdavidxu *   the thread is not canceled.
391211524Sdavidxu */
392277317Skibstatic ssize_t
393277317Skib__thr_read(int fd, void *buf, size_t nbytes)
394112918Sjeff{
395277317Skib	struct pthread *curthread;
396112918Sjeff	ssize_t	ret;
397112918Sjeff
398277317Skib	curthread = _get_curthread();
399212076Sdavidxu	_thr_cancel_enter(curthread);
400112918Sjeff	ret = __sys_read(fd, buf, nbytes);
401212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
402112918Sjeff
403277317Skib	return (ret);
404112918Sjeff}
405112918Sjeff
406211524Sdavidxu/*
407211524Sdavidxu * Cancellation behavior:
408211524Sdavidxu *   Thread may be canceled at start, but if the system call got some data,
409211524Sdavidxu *   the thread is not canceled.
410211524Sdavidxu */
411277317Skibstatic ssize_t
412277317Skib__thr_readv(int fd, const struct iovec *iov, int iovcnt)
413112918Sjeff{
414277317Skib	struct pthread *curthread;
415112918Sjeff	ssize_t ret;
416112918Sjeff
417277317Skib	curthread = _get_curthread();
418212076Sdavidxu	_thr_cancel_enter(curthread);
419112918Sjeff	ret = __sys_readv(fd, iov, iovcnt);
420212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
421277317Skib	return (ret);
422112918Sjeff}
423112918Sjeff
424211524Sdavidxu/*
425211524Sdavidxu * Cancellation behavior:
426211524Sdavidxu *   Thread may be canceled at start, but if the system call got some data,
427211524Sdavidxu *   the thread is not canceled.
428211524Sdavidxu */
429277317Skibstatic ssize_t
430277317Skib__thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
431135301Smtm    socklen_t *fl)
432135301Smtm{
433277317Skib	struct pthread *curthread;
434135301Smtm	ssize_t ret;
435135301Smtm
436277317Skib	curthread = _get_curthread();
437212076Sdavidxu	_thr_cancel_enter(curthread);
438135301Smtm	ret = __sys_recvfrom(s, b, l, f, from, fl);
439212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
440135301Smtm	return (ret);
441135301Smtm}
442135301Smtm
443211524Sdavidxu/*
444211524Sdavidxu * Cancellation behavior:
445211524Sdavidxu *   Thread may be canceled at start, but if the system call got some data,
446211524Sdavidxu *   the thread is not canceled.
447211524Sdavidxu */
448277317Skibstatic ssize_t
449277317Skib__thr_recvmsg(int s, struct msghdr *m, int f)
450135301Smtm{
451277317Skib	struct pthread *curthread;
452135301Smtm	ssize_t ret;
453135301Smtm
454277317Skib	curthread = _get_curthread();
455212076Sdavidxu	_thr_cancel_enter(curthread);
456135301Smtm	ret = __sys_recvmsg(s, m, f);
457212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
458135301Smtm	return (ret);
459135301Smtm}
460135301Smtm
461211524Sdavidxu/*
462211524Sdavidxu * Cancellation behavior:
463211524Sdavidxu *   Thread may be canceled at start, but if the system call returns something,
464211524Sdavidxu *   the thread is not canceled.
465211524Sdavidxu */
466277317Skibstatic int
467277317Skib__thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
468112918Sjeff	struct timeval *timeout)
469112918Sjeff{
470277317Skib	struct pthread *curthread;
471112918Sjeff	int ret;
472112918Sjeff
473277317Skib	curthread = _get_curthread();
474212076Sdavidxu	_thr_cancel_enter(curthread);
475112918Sjeff	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
476212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
477277317Skib	return (ret);
478112918Sjeff}
479112918Sjeff
480211524Sdavidxu/*
481211524Sdavidxu * Cancellation behavior:
482211524Sdavidxu *   Thread may be canceled at start, but if the system call sent
483211524Sdavidxu *   data, the thread is not canceled.
484211524Sdavidxu */
485277317Skibstatic ssize_t
486277317Skib__thr_sendmsg(int s, const struct msghdr *m, int f)
487135301Smtm{
488277317Skib	struct pthread *curthread;
489135301Smtm	ssize_t ret;
490135301Smtm
491277317Skib	curthread = _get_curthread();
492212076Sdavidxu	_thr_cancel_enter(curthread);
493135301Smtm	ret = __sys_sendmsg(s, m, f);
494212076Sdavidxu	_thr_cancel_leave(curthread, ret <= 0);
495135301Smtm	return (ret);
496135301Smtm}
497135301Smtm
498211524Sdavidxu/*
499211524Sdavidxu * Cancellation behavior:
500211524Sdavidxu *   Thread may be canceled at start, but if the system call sent some
501211524Sdavidxu *   data, the thread is not canceled.
502211524Sdavidxu */
503277317Skibstatic ssize_t
504277317Skib__thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
505135301Smtm    socklen_t tl)
506135301Smtm{
507277317Skib	struct pthread *curthread;
508135301Smtm	ssize_t ret;
509135301Smtm
510277317Skib	curthread = _get_curthread();
511212076Sdavidxu	_thr_cancel_enter(curthread);
512135301Smtm	ret = __sys_sendto(s, m, l, f, t, tl);
513212076Sdavidxu	_thr_cancel_leave(curthread, ret <= 0);
514135301Smtm	return (ret);
515135301Smtm}
516135301Smtm
517277317Skibstatic int
518277317Skib__thr_system(const char *string)
519112918Sjeff{
520277317Skib	struct pthread *curthread;
521277317Skib	int ret;
522112918Sjeff
523277317Skib	curthread = _get_curthread();
524164583Sdavidxu	_thr_cancel_enter(curthread);
525277317Skib	ret = __libc_system(string);
526212076Sdavidxu	_thr_cancel_leave(curthread, 1);
527144518Sdavidxu	return (ret);
528112918Sjeff}
529112918Sjeff
530211524Sdavidxu/*
531211524Sdavidxu * Cancellation behavior:
532211524Sdavidxu *   If thread is canceled, the system call is not completed,
533211524Sdavidxu *   this means not all bytes were drained.
534211524Sdavidxu */
535277317Skibstatic int
536277317Skib__thr_tcdrain(int fd)
537112918Sjeff{
538277317Skib	struct pthread *curthread;
539277317Skib	int ret;
540112918Sjeff
541277317Skib	curthread = _get_curthread();
542212076Sdavidxu	_thr_cancel_enter(curthread);
543277317Skib	ret = __libc_tcdrain(fd);
544212076Sdavidxu	_thr_cancel_leave(curthread, ret == -1);
545144518Sdavidxu	return (ret);
546112918Sjeff}
547112918Sjeff
548211524Sdavidxu/*
549211524Sdavidxu * Cancellation behavior:
550211524Sdavidxu *   Thread may be canceled at start, but if the system call returns
551211524Sdavidxu *   a child pid, the thread is not canceled.
552211524Sdavidxu */
553277317Skibstatic pid_t
554277317Skib__thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
555112918Sjeff{
556277317Skib	struct pthread *curthread;
557160662Sdavidxu	pid_t ret;
558160662Sdavidxu
559277317Skib	curthread = _get_curthread();
560212076Sdavidxu	_thr_cancel_enter(curthread);
561277317Skib	ret = __sys_wait4(pid, status, options, rusage);
562212076Sdavidxu	_thr_cancel_leave(curthread, ret <= 0);
563160662Sdavidxu	return (ret);
564160662Sdavidxu}
565160662Sdavidxu
566211524Sdavidxu/*
567211524Sdavidxu * Cancellation behavior:
568281981Skib *   Thread may be canceled at start, but if the system call returns
569281981Skib *   a child pid, the thread is not canceled.
570281981Skib */
571281981Skibstatic pid_t
572281981Skib__thr_wait6(idtype_t idtype, id_t id, int *status, int options,
573281981Skib    struct __wrusage *ru, siginfo_t *infop)
574281981Skib{
575281981Skib	struct pthread *curthread;
576281981Skib	pid_t ret;
577281981Skib
578281981Skib	curthread = _get_curthread();
579281981Skib	_thr_cancel_enter(curthread);
580281981Skib	ret = __sys_wait6(idtype, id, status, options, ru, infop);
581281981Skib	_thr_cancel_leave(curthread, ret <= 0);
582281981Skib	return (ret);
583281981Skib}
584281981Skib
585281981Skib/*
586281981Skib * Cancellation behavior:
587211524Sdavidxu *   Thread may be canceled at start, but if the thread wrote some data,
588211524Sdavidxu *   it is not canceled.
589211524Sdavidxu */
590277317Skibstatic ssize_t
591277317Skib__thr_write(int fd, const void *buf, size_t nbytes)
592112918Sjeff{
593277317Skib	struct pthread *curthread;
594112918Sjeff	ssize_t	ret;
595112918Sjeff
596277317Skib	curthread = _get_curthread();
597212076Sdavidxu	_thr_cancel_enter(curthread);
598112918Sjeff	ret = __sys_write(fd, buf, nbytes);
599212076Sdavidxu	_thr_cancel_leave(curthread, (ret <= 0));
600277317Skib	return (ret);
601112918Sjeff}
602112918Sjeff
603211524Sdavidxu/*
604211524Sdavidxu * Cancellation behavior:
605211524Sdavidxu *   Thread may be canceled at start, but if the thread wrote some data,
606211524Sdavidxu *   it is not canceled.
607211524Sdavidxu */
608277317Skibstatic ssize_t
609277317Skib__thr_writev(int fd, const struct iovec *iov, int iovcnt)
610112918Sjeff{
611277317Skib	struct pthread *curthread;
612112918Sjeff	ssize_t ret;
613112918Sjeff
614277317Skib	curthread = _get_curthread();
615212076Sdavidxu	_thr_cancel_enter(curthread);
616112918Sjeff	ret = __sys_writev(fd, iov, iovcnt);
617212076Sdavidxu	_thr_cancel_leave(curthread, (ret <= 0));
618277317Skib	return (ret);
619112918Sjeff}
620277317Skib
621277317Skibvoid
622277317Skib__thr_interpose_libc(void)
623277317Skib{
624277317Skib
625277317Skib	__set_error_selector(__error_threaded);
626277317Skib#define	SLOT(name)					\
627277317Skib	*(__libc_interposing_slot(INTERPOS_##name)) =	\
628277317Skib	    (interpos_func_t)__thr_##name;
629277317Skib	SLOT(accept);
630277317Skib	SLOT(accept4);
631277317Skib	SLOT(aio_suspend);
632277317Skib	SLOT(close);
633277317Skib	SLOT(connect);
634277317Skib	SLOT(fcntl);
635277317Skib	SLOT(fsync);
636277317Skib	SLOT(fork);
637277317Skib	SLOT(msync);
638277317Skib	SLOT(nanosleep);
639277317Skib	SLOT(openat);
640277317Skib	SLOT(poll);
641277317Skib	SLOT(pselect);
642277317Skib	SLOT(read);
643277317Skib	SLOT(readv);
644277317Skib	SLOT(recvfrom);
645277317Skib	SLOT(recvmsg);
646277317Skib	SLOT(select);
647277317Skib	SLOT(sendmsg);
648277317Skib	SLOT(sendto);
649277317Skib	SLOT(setcontext);
650277317Skib	SLOT(sigaction);
651277317Skib	SLOT(sigprocmask);
652277317Skib	SLOT(sigsuspend);
653277317Skib	SLOT(sigwait);
654277317Skib	SLOT(sigtimedwait);
655277317Skib	SLOT(sigwaitinfo);
656277317Skib	SLOT(swapcontext);
657277317Skib	SLOT(system);
658277317Skib	SLOT(tcdrain);
659277317Skib	SLOT(wait4);
660277317Skib	SLOT(write);
661277317Skib	SLOT(writev);
662278875Skib	SLOT(spinlock);
663278875Skib	SLOT(spinunlock);
664281454Skib	SLOT(kevent);
665281981Skib	SLOT(wait6);
666281981Skib	SLOT(ppoll);
667296732Skib	SLOT(map_stacks_exec);
668277317Skib#undef SLOT
669277317Skib	*(__libc_interposing_slot(
670277317Skib	    INTERPOS__pthread_mutex_init_calloc_cb)) =
671277317Skib	    (interpos_func_t)_pthread_mutex_init_calloc_cb;
672277317Skib}
673