1 /*
2  * Copyright (C) 2005 David Xu <davidxu@freebsd.org>.
3  * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>.
4  * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice(s), this list of conditions and the following disclaimer as
12  *    the first lines of this file unmodified other than the possible
13  *    addition of one or more copyright notices.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice(s), this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $DragonFly: src/lib/libthread_xu/thread/thr_syscalls.c,v 1.8 2008/01/10 22:30:27 nth Exp $
32  */
33 
34 /*
35  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
36  * All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. All advertising materials mentioning features or use of this software
47  *    must display the following acknowledgement:
48  *	This product includes software developed by John Birrell.
49  * 4. Neither the name of the author nor the names of any co-contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  */
66 
67 #include <sys/types.h>
68 #include <sys/mman.h>
69 #include <sys/param.h>
70 #include <sys/select.h>
71 #include <sys/signalvar.h>
72 #include <sys/socket.h>
73 #include <sys/stat.h>
74 #include <sys/time.h>
75 #include <sys/uio.h>
76 #include <sys/wait.h>
77 
78 #include <machine/tls.h>
79 
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 
94 #include "thr_private.h"
95 
96 extern int	__creat(const char *, mode_t);
97 extern int	__pause(void);
98 extern int	__sys_pselect(int, fd_set *, fd_set *, fd_set *,
99 			const struct timespec *, const sigset_t *);
100 extern unsigned	__sleep(unsigned int);
101 extern int	__system(const char *);
102 extern int	__tcdrain(int);
103 extern int	__usleep(unsigned);
104 extern pid_t	__wait(int *);
105 extern pid_t	__waitpid(pid_t, int *, int);
106 extern int	__sys_aio_suspend(const struct aiocb * const[], int,
107 			const struct timespec *);
108 extern int	__sys_accept(int, struct sockaddr *, socklen_t *);
109 extern int	__sys_connect(int, const struct sockaddr *, socklen_t);
110 extern int	__sys_fsync(int);
111 extern int	__sys_msync(void *, size_t, int);
112 extern int	__sys_poll(struct pollfd *, unsigned, int);
113 extern int	__sys_ppoll(struct pollfd *, unsigned, const struct timespec *,
114 			const sigset_t *);
115 extern ssize_t	__sys_recv(int, void *, size_t, int);
116 extern ssize_t	__sys_recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *);
117 extern ssize_t	__sys_recvmsg(int, struct msghdr *, int);
118 extern int	__sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
119 extern int	__sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *,
120 			off_t *, int);
121 extern ssize_t	__sys_sendmsg(int, const struct msghdr *, int);
122 extern ssize_t	__sys_sendto(int, const void *,size_t, int, const struct sockaddr *, socklen_t);
123 extern ssize_t	__sys_readv(int, const struct iovec *, int);
124 extern pid_t	__sys_wait4(pid_t, int *, int, struct rusage *);
125 extern ssize_t	__sys_writev(int, const struct iovec *, int);
126 
127 int	___creat(const char *, mode_t);
128 int	___usleep(unsigned);
129 int	__accept(int, struct sockaddr *, socklen_t *);
130 int	__close(int);
131 int	__connect(int, const struct sockaddr *, socklen_t);
132 int	__fcntl(int, int,...);
133 int	__fsync(int);
134 int	__msync(void *, size_t, int);
135 int	__nanosleep(const struct timespec *, struct timespec *);
136 int	__open(const char *, int,...);
137 int	__openat(int fd, const char *, int,...);
138 int	__poll(struct pollfd *, unsigned int, int);
139 int	__ppoll(struct pollfd *, unsigned int, const struct timespec *,
140 		const sigset_t *);
141 ssize_t	__read(int, void *buf, size_t);
142 ssize_t	__readv(int, const struct iovec *, int);
143 ssize_t	__recvfrom(int, void *, size_t, int f, struct sockaddr *, socklen_t *);
144 ssize_t	__recvmsg(int, struct msghdr *, int);
145 int	__select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
146 ssize_t	__sendmsg(int, const struct msghdr *, int);
147 ssize_t	__sendto(int, const void *, size_t, int,
148 		const struct sockaddr *, socklen_t);
149 pid_t	__wait4(pid_t, int *, int, struct rusage *);
150 ssize_t	__write(int, const void *, size_t);
151 ssize_t	__writev(int, const struct iovec *, int);
152 int	_aio_suspend(const struct aiocb * const iocbs[], int,
153 		const struct timespec *);
154 int	_pause(void);
155 int	__pselect(int, fd_set *, fd_set *, fd_set *,
156 		const struct timespec *, const sigset_t *);
157 int	_raise(int);
158 unsigned	_sleep(unsigned);
159 int	_system(const char *);
160 int	_tcdrain(int);
161 #if 0
162 int	_vfork(void);
163 #endif
164 pid_t	_wait(int *);
165 pid_t	_waitpid(pid_t wpid, int *status, int options);
166 
167 int
168 __accept(int s, struct sockaddr *addr, socklen_t *addrlen)
169 {
170 	struct pthread *curthread;
171 	int oldcancel;
172 	int ret;
173 
174 	curthread = tls_get_curthread();
175 	oldcancel = _thr_cancel_enter(curthread);
176 	ret = __sys_accept(s, addr, addrlen);
177 	_thr_cancel_leave(curthread, oldcancel);
178 
179  	return (ret);
180 }
181 
182 __strong_reference(__accept, accept);
183 
184 int
185 _aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
186     timespec *timeout)
187 {
188 	struct pthread *curthread = tls_get_curthread();
189 	int oldcancel;
190 	int ret;
191 
192 	oldcancel = _thr_cancel_enter(curthread);
193 	ret = __sys_aio_suspend(iocbs, niocb, timeout);
194 	_thr_cancel_leave(curthread, oldcancel);
195 
196 	return (ret);
197 }
198 
199 __strong_reference(_aio_suspend, aio_suspend);
200 
201 int
202 __close(int fd)
203 {
204 	struct pthread	*curthread = tls_get_curthread();
205 	int	oldcancel;
206 	int	ret;
207 
208 	oldcancel = _thr_cancel_enter(curthread);
209 	ret = __sys_close(fd);
210 	_thr_cancel_leave(curthread, oldcancel);
211 
212 	return (ret);
213 }
214 
215 __strong_reference(__close, close);
216 
217 int
218 __connect(int fd, const struct sockaddr *name, socklen_t namelen)
219 {
220 	struct pthread *curthread = tls_get_curthread();
221 	int oldcancel;
222 	int ret;
223 
224 	oldcancel = _thr_cancel_enter(curthread);
225 	ret = __sys_connect(fd, name, namelen);
226 	_thr_cancel_leave(curthread, oldcancel);
227 
228  	return (ret);
229 }
230 
231 __strong_reference(__connect, connect);
232 
233 int
234 ___creat(const char *path, mode_t mode)
235 {
236 	struct pthread *curthread = tls_get_curthread();
237 	int oldcancel;
238 	int ret;
239 
240 	oldcancel = _thr_cancel_enter(curthread);
241 	ret = __creat(path, mode);
242 	_thr_cancel_leave(curthread, oldcancel);
243 
244 	return ret;
245 }
246 
247 __strong_reference(___creat, creat);
248 
249 int
250 __fcntl(int fd, int cmd,...)
251 {
252 	struct pthread *curthread = tls_get_curthread();
253 	int	oldcancel;
254 	int	ret;
255 	va_list	ap;
256 
257 	oldcancel = _thr_cancel_enter(curthread);
258 
259 	va_start(ap, cmd);
260 	switch (cmd) {
261 	case F_DUPFD:
262 		ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
263 		break;
264 	case F_SETFD:
265 	case F_SETFL:
266 		ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
267 		break;
268 	case F_GETFD:
269 	case F_GETFL:
270 		ret = __sys_fcntl(fd, cmd);
271 		break;
272 	default:
273 		ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
274 	}
275 	va_end(ap);
276 
277 	_thr_cancel_leave(curthread, oldcancel);
278 
279 	return (ret);
280 }
281 
282 __strong_reference(__fcntl, fcntl);
283 
284 int
285 __fsync(int fd)
286 {
287 	struct pthread *curthread = tls_get_curthread();
288 	int	oldcancel;
289 	int	ret;
290 
291 	oldcancel = _thr_cancel_enter(curthread);
292 	ret = __sys_fsync(fd);
293 	_thr_cancel_leave(curthread, oldcancel);
294 
295 	return (ret);
296 }
297 
298 __strong_reference(__fsync, fsync);
299 
300 int
301 __msync(void *addr, size_t len, int flags)
302 {
303 	struct pthread *curthread = tls_get_curthread();
304 	int	oldcancel;
305 	int	ret;
306 
307 	oldcancel = _thr_cancel_enter(curthread);
308 	ret = __sys_msync(addr, len, flags);
309 	_thr_cancel_leave(curthread, oldcancel);
310 
311 	return ret;
312 }
313 
314 __strong_reference(__msync, msync);
315 
316 int
317 __nanosleep(const struct timespec *time_to_sleep,
318     struct timespec *time_remaining)
319 {
320 	struct pthread *curthread = tls_get_curthread();
321 	int		oldcancel;
322 	int		ret;
323 
324 	oldcancel = _thr_cancel_enter(curthread);
325 	ret = __sys_nanosleep(time_to_sleep, time_remaining);
326 	_thr_cancel_leave(curthread, oldcancel);
327 
328 	return (ret);
329 }
330 
331 __strong_reference(__nanosleep, nanosleep);
332 
333 int
334 __open(const char *path, int flags,...)
335 {
336 	struct pthread *curthread = tls_get_curthread();
337 	int	oldcancel;
338 	int	ret;
339 	int	mode = 0;
340 	va_list	ap;
341 
342 	oldcancel = _thr_cancel_enter(curthread);
343 
344 	/* Check if the file is being created: */
345 	if (flags & O_CREAT) {
346 		/* Get the creation mode: */
347 		va_start(ap, flags);
348 		mode = va_arg(ap, int);
349 		va_end(ap);
350 	}
351 
352 	ret = __sys_open(path, flags, mode);
353 
354 	_thr_cancel_leave(curthread, oldcancel);
355 
356 	return ret;
357 }
358 
359 __strong_reference(__open, open);
360 
361 int
362 __openat(int fd, const char *path, int flags,...)
363 {
364 	struct pthread *curthread = tls_get_curthread();
365 	int	oldcancel;
366 	int	ret;
367 	int	mode = 0;
368 	va_list	ap;
369 
370 	oldcancel = _thr_cancel_enter(curthread);
371 
372 	/* Check if the file is being created: */
373 	if (flags & O_CREAT) {
374 		/* Get the creation mode: */
375 		va_start(ap, flags);
376 		mode = va_arg(ap, int);
377 		va_end(ap);
378 	}
379 
380 	ret = __sys_openat(fd, path, flags, mode);
381 
382 	_thr_cancel_leave(curthread, oldcancel);
383 
384 	return ret;
385 }
386 
387 __strong_reference(__openat, openat);
388 
389 int
390 _pause(void)
391 {
392 	struct pthread *curthread = tls_get_curthread();
393 	int	oldcancel;
394 	int	ret;
395 
396 	oldcancel = _thr_cancel_enter(curthread);
397 	ret = __pause();
398 	_thr_cancel_leave(curthread, oldcancel);
399 
400 	return ret;
401 }
402 
403 __strong_reference(_pause, pause);
404 
405 int
406 __poll(struct pollfd *fds, unsigned int nfds, int timeout)
407 {
408 	struct pthread *curthread = tls_get_curthread();
409 	int oldcancel;
410 	int ret;
411 
412 	oldcancel = _thr_cancel_enter(curthread);
413 	ret = __sys_poll(fds, nfds, timeout);
414 	_thr_cancel_leave(curthread, oldcancel);
415 
416 	return ret;
417 }
418 
419 __strong_reference(__poll, poll);
420 
421 int
422 __ppoll(struct pollfd *fds, unsigned int nfds, const struct timespec *ts,
423 	const sigset_t *mask)
424 {
425 	struct pthread *curthread = tls_get_curthread();
426 	int oldcancel;
427 	int ret;
428 
429 	oldcancel = _thr_cancel_enter(curthread);
430 	ret = __sys_ppoll(fds, nfds, ts, mask);
431 	_thr_cancel_leave(curthread, oldcancel);
432 
433 	return ret;
434 }
435 
436 __strong_reference(__ppoll, ppoll);
437 
438 int
439 __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
440 	const struct timespec *timo, const sigset_t *mask)
441 {
442 	struct pthread *curthread = tls_get_curthread();
443 	int oldcancel;
444 	int ret;
445 
446 	oldcancel = _thr_cancel_enter(curthread);
447 	ret = __sys_pselect(count, rfds, wfds, efds, timo, mask);
448 	_thr_cancel_leave(curthread, oldcancel);
449 
450 	return (ret);
451 }
452 __strong_reference(__pselect, pselect);
453 
454 
455 int
456 _raise(int sig)
457 {
458 	int ret;
459 
460 	if (!_thr_isthreaded())
461 		ret = kill(getpid(), sig);
462 	else
463 		ret = _thr_send_sig(tls_get_curthread(), sig);
464 	return (ret);
465 }
466 
467 __strong_reference(_raise, raise);
468 
469 ssize_t
470 __read(int fd, void *buf, size_t nbytes)
471 {
472 	struct pthread *curthread = tls_get_curthread();
473 	int oldcancel;
474 	ssize_t	ret;
475 
476 	oldcancel = _thr_cancel_enter(curthread);
477 	ret = __sys_read(fd, buf, nbytes);
478 	_thr_cancel_leave(curthread, oldcancel);
479 
480 	return ret;
481 }
482 
483 __strong_reference(__read, read);
484 
485 ssize_t
486 __readv(int fd, const struct iovec *iov, int iovcnt)
487 {
488 	struct pthread *curthread = tls_get_curthread();
489 	int oldcancel;
490 	ssize_t ret;
491 
492 	oldcancel = _thr_cancel_enter(curthread);
493 	ret = __sys_readv(fd, iov, iovcnt);
494 	_thr_cancel_leave(curthread, oldcancel);
495 
496 	return ret;
497 }
498 
499 __strong_reference(__readv, readv);
500 
501 ssize_t
502 __recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
503     socklen_t *fl)
504 {
505 	struct pthread *curthread = tls_get_curthread();
506 	int oldcancel;
507 	ssize_t ret;
508 
509 	oldcancel = _thr_cancel_enter(curthread);
510 	ret = __sys_recvfrom(s, b, l, f, from, fl);
511 	_thr_cancel_leave(curthread, oldcancel);
512 	return (ret);
513 }
514 
515 __strong_reference(__recvfrom, recvfrom);
516 
517 ssize_t
518 __recvmsg(int s, struct msghdr *m, int f)
519 {
520 	struct pthread *curthread = tls_get_curthread();
521 	ssize_t ret;
522 	int oldcancel;
523 
524 	oldcancel = _thr_cancel_enter(curthread);
525 	ret = __sys_recvmsg(s, m, f);
526 	_thr_cancel_leave(curthread, oldcancel);
527 	return (ret);
528 }
529 
530 __strong_reference(__recvmsg, recvmsg);
531 
532 int
533 __select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
534 	struct timeval *timeout)
535 {
536 	struct pthread *curthread = tls_get_curthread();
537 	int oldcancel;
538 	int ret;
539 
540 	oldcancel = _thr_cancel_enter(curthread);
541 	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
542 	_thr_cancel_leave(curthread, oldcancel);
543 	return ret;
544 }
545 
546 __strong_reference(__select, select);
547 
548 ssize_t
549 __sendmsg(int s, const struct msghdr *m, int f)
550 {
551 	struct pthread *curthread = tls_get_curthread();
552 	ssize_t ret;
553 	int oldcancel;
554 
555 	oldcancel = _thr_cancel_enter(curthread);
556 	ret = __sys_sendmsg(s, m, f);
557 	_thr_cancel_leave(curthread, oldcancel);
558 	return (ret);
559 }
560 
561 __strong_reference(__sendmsg, sendmsg);
562 
563 ssize_t
564 __sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
565     socklen_t tl)
566 {
567 	struct pthread *curthread = tls_get_curthread();
568 	ssize_t ret;
569 	int oldcancel;
570 
571 	oldcancel = _thr_cancel_enter(curthread);
572 	ret = __sys_sendto(s, m, l, f, t, tl);
573 	_thr_cancel_leave(curthread, oldcancel);
574 	return (ret);
575 }
576 
577 __strong_reference(__sendto, sendto);
578 
579 unsigned int
580 _sleep(unsigned int seconds)
581 {
582 	struct pthread *curthread = tls_get_curthread();
583 	int		oldcancel;
584 	unsigned int	ret;
585 
586 	oldcancel = _thr_cancel_enter(curthread);
587 	ret = __sleep(seconds);
588 	_thr_cancel_leave(curthread, oldcancel);
589 
590 	return (ret);
591 }
592 
593 int
594 _system(const char *string)
595 {
596 	struct pthread *curthread = tls_get_curthread();
597 	int	oldcancel;
598 	int	ret;
599 
600 	oldcancel = _thr_cancel_enter(curthread);
601 	ret = __system(string);
602 	_thr_cancel_leave(curthread, oldcancel);
603 
604 	return ret;
605 }
606 
607 __strong_reference(_system, system);
608 
609 int
610 _tcdrain(int fd)
611 {
612 	struct pthread *curthread = tls_get_curthread();
613 	int	oldcancel;
614 	int	ret;
615 
616 	oldcancel = _thr_cancel_enter(curthread);
617 	ret = __tcdrain(fd);
618 	_thr_cancel_leave(curthread, oldcancel);
619 
620 	return (ret);
621 }
622 
623 __strong_reference(_tcdrain, tcdrain);
624 
625 int
626 ___usleep(unsigned int useconds)
627 {
628 	struct pthread *curthread = tls_get_curthread();
629 	int		oldcancel;
630 	int		ret;
631 
632 	oldcancel = _thr_cancel_enter(curthread);
633 	ret = __usleep(useconds);
634 	_thr_cancel_leave(curthread, oldcancel);
635 
636 	return (ret);
637 }
638 
639 __strong_reference(___usleep, usleep);
640 
641 #if 0
642 /*
643  * REMOVED - vfork() works as per normal.  In a threaded environment vfork()
644  *	     blocks the calling thread only and not other threads.
645  */
646 int
647 _vfork(void)
648 {
649 	return (fork());
650 }
651 
652 __strong_reference(_vfork, vfork);
653 #endif
654 
655 pid_t
656 _wait(int *istat)
657 {
658 	struct pthread *curthread = tls_get_curthread();
659 	int	oldcancel;
660 	pid_t	ret;
661 
662 	oldcancel = _thr_cancel_enter(curthread);
663 	ret = __wait(istat);
664 	_thr_cancel_leave(curthread, oldcancel);
665 
666 	return ret;
667 }
668 
669 __strong_reference(_wait, wait);
670 
671 pid_t
672 __wait4(pid_t pid, int *istat, int options, struct rusage *rusage)
673 {
674 	struct pthread *curthread = tls_get_curthread();
675 	int oldcancel;
676 	pid_t ret;
677 
678 	oldcancel = _thr_cancel_enter(curthread);
679 	ret = __sys_wait4(pid, istat, options, rusage);
680 	_thr_cancel_leave(curthread, oldcancel);
681 
682 	return ret;
683 }
684 
685 __strong_reference(__wait4, wait4);
686 
687 pid_t
688 _waitpid(pid_t wpid, int *status, int options)
689 {
690 	struct pthread *curthread = tls_get_curthread();
691 	int	oldcancel;
692 	pid_t	ret;
693 
694 	oldcancel = _thr_cancel_enter(curthread);
695 	ret = __waitpid(wpid, status, options);
696 	_thr_cancel_leave(curthread, oldcancel);
697 
698 	return ret;
699 }
700 
701 __strong_reference(_waitpid, waitpid);
702 
703 ssize_t
704 __write(int fd, const void *buf, size_t nbytes)
705 {
706 	struct pthread *curthread = tls_get_curthread();
707 	int	oldcancel;
708 	ssize_t	ret;
709 
710 	oldcancel = _thr_cancel_enter(curthread);
711 	ret = __sys_write(fd, buf, nbytes);
712 	_thr_cancel_leave(curthread, oldcancel);
713 
714 	return ret;
715 }
716 
717 __strong_reference(__write, write);
718 
719 ssize_t
720 __writev(int fd, const struct iovec *iov, int iovcnt)
721 {
722 	struct pthread *curthread = tls_get_curthread();
723 	int	oldcancel;
724 	ssize_t ret;
725 
726 	oldcancel = _thr_cancel_enter(curthread);
727 	ret = __sys_writev(fd, iov, iovcnt);
728 	_thr_cancel_leave(curthread, oldcancel);
729 
730 	return ret;
731 }
732 
733 __strong_reference(__writev, writev);
734 
735