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