1 /*	$NetBSD: pthread_cancelstub.c,v 1.31 2011/01/26 18:48:57 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Nathan J. Williams and Andrew Doran.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE 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 BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: pthread_cancelstub.c,v 1.31 2011/01/26 18:48:57 christos Exp $");
34 
35 #ifndef lint
36 
37 
38 /*
39  * This is necessary because the names are always weak (they are not
40  * POSIX functions).
41  */
42 #define	fsync_range	_fsync_range
43 #define	pollts		_pollts
44 
45 /*
46  * XXX this is necessary to get the prototypes for the __sigsuspend14
47  * XXX and __msync13 internal names, instead of the application-visible
48  * XXX sigsuspend and msync names. It's kind of gross, but we're pretty
49  * XXX intimate with libc already.
50  */
51 #define __LIBC12_SOURCE__
52 
53 #define __ssp_weak_name(fun)	_cancelstub_ ## fun
54 
55 #include <sys/msg.h>
56 #include <sys/types.h>
57 #include <sys/uio.h>
58 #include <sys/wait.h>
59 #include <aio.h>
60 #include <fcntl.h>
61 #include <mqueue.h>
62 #include <poll.h>
63 #include <stdarg.h>
64 #include <unistd.h>
65 
66 #include <signal.h>
67 #include <sys/mman.h>
68 #include <sys/select.h>
69 #include <sys/socket.h>
70 #include <sys/event.h>
71 
72 #include <compat/sys/mman.h>
73 #include <compat/sys/poll.h>
74 #include <compat/sys/select.h>
75 #include <compat/sys/event.h>
76 #include <compat/sys/wait.h>
77 #include <compat/include/mqueue.h>
78 #include <compat/include/signal.h>
79 
80 #include "pthread.h"
81 #include "pthread_int.h"
82 
83 int	pthread__cancel_stub_binder;
84 
85 int	_sys_accept(int, struct sockaddr *, socklen_t *);
86 int	_sys___aio_suspend50(const struct aiocb * const [], int,
87 	    const struct timespec *);
88 int	__aio_suspend50(const struct aiocb * const [], int,
89 	    const struct timespec *);
90 int	_sys_close(int);
91 int	_sys_connect(int, const struct sockaddr *, socklen_t);
92 int	_sys_fcntl(int, int, ...);
93 int	_sys_fdatasync(int);
94 int	_sys_fsync(int);
95 int	_sys_fsync_range(int, int, off_t, off_t);
96 int	_sys___kevent50(int, const struct kevent *, size_t, struct kevent *,
97 	    size_t, const struct timespec *);
98 int	_sys_mq_send(mqd_t, const char *, size_t, unsigned);
99 ssize_t	_sys_mq_receive(mqd_t, char *, size_t, unsigned *);
100 int	_sys___mq_timedsend50(mqd_t, const char *, size_t, unsigned,
101 	    const struct timespec *);
102 ssize_t	_sys___mq_timedreceive50(mqd_t, char *, size_t, unsigned *,
103 	    const struct timespec *);
104 ssize_t	_sys_msgrcv(int, void *, size_t, long, int);
105 int	_sys_msgsnd(int, const void *, size_t, int);
106 int	_sys___msync13(void *, size_t, int);
107 int	_sys___nanosleep50(const struct timespec *, struct timespec *);
108 int	__nanosleep50(const struct timespec *, struct timespec *);
109 int	_sys_open(const char *, int, ...);
110 int	_sys_poll(struct pollfd *, nfds_t, int);
111 int	_sys___pollts50(struct pollfd *, nfds_t, const struct timespec *,
112 	    const sigset_t *);
113 ssize_t	_sys_pread(int, void *, size_t, off_t);
114 int	_sys___pselect50(int, fd_set *, fd_set *, fd_set *,
115 	    const struct timespec *, const sigset_t *);
116 ssize_t	_sys_pwrite(int, const void *, size_t, off_t);
117 ssize_t	_sys_read(int, void *, size_t);
118 ssize_t	_sys_readv(int, const struct iovec *, int);
119 int	_sys___select50(int, fd_set *, fd_set *, fd_set *, struct timeval *);
120 int	_sys___wait450(pid_t, int *, int, struct rusage *);
121 ssize_t	_sys_write(int, const void *, size_t);
122 ssize_t	_sys_writev(int, const struct iovec *, int);
123 int	_sys___sigsuspend14(const sigset_t *);
124 int	____sigtimedwait50(const sigset_t * __restrict, siginfo_t * __restrict,
125 	    struct timespec * __restrict);
126 int	__sigsuspend14(const sigset_t *);
127 
128 #define TESTCANCEL(id) 	do {						\
129 	if (__predict_false((id)->pt_cancel))				\
130 		pthread__cancelled();					\
131 	} while (/*CONSTCOND*/0)
132 
133 
134 int
135 accept(int s, struct sockaddr *addr, socklen_t *addrlen)
136 {
137 	int retval;
138 	pthread_t self;
139 
140 	self = pthread__self();
141 	TESTCANCEL(self);
142 	retval = _sys_accept(s, addr, addrlen);
143 	TESTCANCEL(self);
144 
145 	return retval;
146 }
147 
148 int
149 __aio_suspend50(const struct aiocb * const list[], int nent,
150     const struct timespec *timeout)
151 {
152 	int retval;
153 	pthread_t self;
154 
155 	self = pthread__self();
156 	TESTCANCEL(self);
157 	retval = _sys___aio_suspend50(list, nent, timeout);
158 	TESTCANCEL(self);
159 
160 	return retval;
161 }
162 
163 int
164 __kevent50(int fd, const struct kevent *ev, size_t nev, struct kevent *rev,
165     size_t nrev, const struct timespec *ts)
166 {
167 	int retval;
168 	pthread_t self;
169 
170 	self = pthread__self();
171 	TESTCANCEL(self);
172 	retval = _sys___kevent50(fd, ev, nev, rev, nrev, ts);
173 	TESTCANCEL(self);
174 
175 	return retval;
176 }
177 
178 int
179 close(int d)
180 {
181 	int retval;
182 	pthread_t self;
183 
184 	self = pthread__self();
185 	TESTCANCEL(self);
186 	retval = _sys_close(d);
187 	TESTCANCEL(self);
188 
189 	return retval;
190 }
191 
192 int
193 connect(int s, const struct sockaddr *addr, socklen_t namelen)
194 {
195 	int retval;
196 	pthread_t self;
197 
198 	self = pthread__self();
199 	TESTCANCEL(self);
200 	retval = _sys_connect(s, addr, namelen);
201 	TESTCANCEL(self);
202 
203 	return retval;
204 }
205 
206 int
207 fcntl(int fd, int cmd, ...)
208 {
209 	int retval;
210 	pthread_t self;
211 	va_list ap;
212 
213 	self = pthread__self();
214 	TESTCANCEL(self);
215 	va_start(ap, cmd);
216 	retval = _sys_fcntl(fd, cmd, va_arg(ap, void *));
217 	va_end(ap);
218 	TESTCANCEL(self);
219 
220 	return retval;
221 }
222 
223 int
224 fdatasync(int d)
225 {
226 	int retval;
227 	pthread_t self;
228 
229 	self = pthread__self();
230 	TESTCANCEL(self);
231 	retval = _sys_fdatasync(d);
232 	TESTCANCEL(self);
233 
234 	return retval;
235 }
236 
237 int
238 fsync(int d)
239 {
240 	int retval;
241 	pthread_t self;
242 
243 	self = pthread__self();
244 	TESTCANCEL(self);
245 	retval = _sys_fsync(d);
246 	TESTCANCEL(self);
247 
248 	return retval;
249 }
250 
251 int
252 fsync_range(int d, int f, off_t s, off_t e)
253 {
254 	int retval;
255 	pthread_t self;
256 
257 	self = pthread__self();
258 	TESTCANCEL(self);
259 	retval = _sys_fsync_range(d, f, s, e);
260 	TESTCANCEL(self);
261 
262 	return retval;
263 }
264 
265 int
266 mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio)
267 {
268 	int retval;
269 	pthread_t self;
270 
271 	self = pthread__self();
272 	TESTCANCEL(self);
273 	retval = _sys_mq_send(mqdes, msg_ptr, msg_len, msg_prio);
274 	TESTCANCEL(self);
275 
276 	return retval;
277 }
278 
279 ssize_t
280 mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio)
281 {
282 	ssize_t retval;
283 	pthread_t self;
284 
285 	self = pthread__self();
286 	TESTCANCEL(self);
287 	retval = _sys_mq_receive(mqdes, msg_ptr, msg_len, msg_prio);
288 	TESTCANCEL(self);
289 
290 	return retval;
291 }
292 
293 int
294 __mq_timedsend50(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
295     unsigned msg_prio, const struct timespec *abst)
296 {
297 	int retval;
298 	pthread_t self;
299 
300 	self = pthread__self();
301 	TESTCANCEL(self);
302 	retval = _sys___mq_timedsend50(mqdes, msg_ptr, msg_len, msg_prio, abst);
303 	TESTCANCEL(self);
304 
305 	return retval;
306 }
307 
308 ssize_t
309 __mq_timedreceive50(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio,
310     const struct timespec *abst)
311 {
312 	ssize_t retval;
313 	pthread_t self;
314 
315 	self = pthread__self();
316 	TESTCANCEL(self);
317 	retval = _sys___mq_timedreceive50(mqdes, msg_ptr, msg_len, msg_prio, abst);
318 	TESTCANCEL(self);
319 
320 	return retval;
321 }
322 
323 ssize_t
324 msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
325 {
326 	ssize_t retval;
327 	pthread_t self;
328 
329 	self = pthread__self();
330 	TESTCANCEL(self);
331 	retval = _sys_msgrcv(msgid, msgp, msgsz, msgtyp, msgflg);
332 	TESTCANCEL(self);
333 
334 	return retval;
335 }
336 
337 int
338 msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)
339 {
340 	int retval;
341 	pthread_t self;
342 
343 	self = pthread__self();
344 	TESTCANCEL(self);
345 	retval = _sys_msgsnd(msgid, msgp, msgsz, msgflg);
346 	TESTCANCEL(self);
347 
348 	return retval;
349 }
350 
351 int
352 __msync13(void *addr, size_t len, int flags)
353 {
354 	int retval;
355 	pthread_t self;
356 
357 	self = pthread__self();
358 	TESTCANCEL(self);
359 	retval = _sys___msync13(addr, len, flags);
360 	TESTCANCEL(self);
361 
362 	return retval;
363 }
364 
365 int
366 open(const char *path, int flags, ...)
367 {
368 	int retval;
369 	pthread_t self;
370 	va_list ap;
371 
372 	self = pthread__self();
373 	TESTCANCEL(self);
374 	va_start(ap, flags);
375 	retval = _sys_open(path, flags, va_arg(ap, mode_t));
376 	va_end(ap);
377 	TESTCANCEL(self);
378 
379 	return retval;
380 }
381 
382 int
383 __nanosleep50(const struct timespec *rqtp, struct timespec *rmtp)
384 {
385 	int retval;
386 	pthread_t self;
387 
388 	self = pthread__self();
389 	TESTCANCEL(self);
390 	/*
391 	 * For now, just nanosleep.  In the future, maybe pass a ucontext_t
392 	 * to _lwp_nanosleep() and allow it to recycle our kernel stack.
393 	 */
394 	retval = _sys___nanosleep50(rqtp, rmtp);
395 	TESTCANCEL(self);
396 
397 	return retval;
398 }
399 
400 int
401 poll(struct pollfd *fds, nfds_t nfds, int timeout)
402 {
403 	int retval;
404 	pthread_t self;
405 
406 	self = pthread__self();
407 	TESTCANCEL(self);
408 	retval = _sys_poll(fds, nfds, timeout);
409 	TESTCANCEL(self);
410 
411 	return retval;
412 }
413 
414 int
415 __pollts50(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
416     const sigset_t *sigmask)
417 {
418 	int retval;
419 	pthread_t self;
420 
421 	self = pthread__self();
422 	TESTCANCEL(self);
423 	retval = _sys___pollts50(fds, nfds, ts, sigmask);
424 	TESTCANCEL(self);
425 
426 	return retval;
427 }
428 
429 ssize_t
430 pread(int d, void *buf, size_t nbytes, off_t offset)
431 {
432 	ssize_t retval;
433 	pthread_t self;
434 
435 	self = pthread__self();
436 	TESTCANCEL(self);
437 	retval = _sys_pread(d, buf, nbytes, offset);
438 	TESTCANCEL(self);
439 
440 	return retval;
441 }
442 
443 int
444 __pselect50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
445     const struct timespec *timeout, const sigset_t *sigmask)
446 {
447 	int retval;
448 	pthread_t self;
449 
450 	self = pthread__self();
451 	TESTCANCEL(self);
452 	retval = _sys___pselect50(nfds, readfds, writefds, exceptfds, timeout,
453 	    sigmask);
454 	TESTCANCEL(self);
455 
456 	return retval;
457 }
458 
459 ssize_t
460 pwrite(int d, const void *buf, size_t nbytes, off_t offset)
461 {
462 	ssize_t retval;
463 	pthread_t self;
464 
465 	self = pthread__self();
466 	TESTCANCEL(self);
467 	retval = _sys_pwrite(d, buf, nbytes, offset);
468 	TESTCANCEL(self);
469 
470 	return retval;
471 }
472 
473 #if _FORTIFY_SOURCE > 0
474 #define STUB(fun) __ssp_weak_name(fun)
475 ssize_t _sys_readlink(const char * __restrict, char * __restrict, size_t);
476 ssize_t
477 STUB(readlink)(const char * __restrict path, char * __restrict buf,
478     size_t bufsiz)
479 {
480 	return _sys_readlink(path, buf, bufsiz);
481 }
482 
483 char *_sys_getcwd(char *, size_t);
484 char *
485 STUB(getcwd)(char *buf, size_t size)
486 {
487 	return _sys_getcwd(buf, size);
488 }
489 #else
490 #define STUB(fun) fun
491 #endif
492 
493 ssize_t
494 STUB(read)(int d, void *buf, size_t nbytes)
495 {
496 	ssize_t retval;
497 	pthread_t self;
498 
499 	self = pthread__self();
500 	TESTCANCEL(self);
501 	retval = _sys_read(d, buf, nbytes);
502 	TESTCANCEL(self);
503 
504 	return retval;
505 }
506 
507 ssize_t
508 readv(int d, const struct iovec *iov, int iovcnt)
509 {
510 	ssize_t retval;
511 	pthread_t self;
512 
513 	self = pthread__self();
514 	TESTCANCEL(self);
515 	retval = _sys_readv(d, iov, iovcnt);
516 	TESTCANCEL(self);
517 
518 	return retval;
519 }
520 
521 int
522 __select50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
523     struct timeval *timeout)
524 {
525 	int retval;
526 	pthread_t self;
527 
528 	self = pthread__self();
529 	TESTCANCEL(self);
530 	retval = _sys___select50(nfds, readfds, writefds, exceptfds, timeout);
531 	TESTCANCEL(self);
532 
533 	return retval;
534 }
535 
536 pid_t
537 __wait450(pid_t wpid, int *status, int options, struct rusage *rusage)
538 {
539 	pid_t retval;
540 	pthread_t self;
541 
542 	self = pthread__self();
543 	TESTCANCEL(self);
544 	retval = _sys___wait450(wpid, status, options, rusage);
545 	TESTCANCEL(self);
546 
547 	return retval;
548 }
549 
550 ssize_t
551 write(int d, const void *buf, size_t nbytes)
552 {
553 	ssize_t retval;
554 	pthread_t self;
555 
556 	self = pthread__self();
557 	TESTCANCEL(self);
558 	retval = _sys_write(d, buf, nbytes);
559 	TESTCANCEL(self);
560 
561 	return retval;
562 }
563 
564 ssize_t
565 writev(int d, const struct iovec *iov, int iovcnt)
566 {
567 	ssize_t retval;
568 	pthread_t self;
569 
570 	self = pthread__self();
571 	TESTCANCEL(self);
572 	retval = _sys_writev(d, iov, iovcnt);
573 	TESTCANCEL(self);
574 
575 	return retval;
576 }
577 
578 int
579 __sigsuspend14(const sigset_t *sigmask)
580 {
581 	pthread_t self;
582 	int retval;
583 
584 	self = pthread__self();
585 	TESTCANCEL(self);
586 	retval = _sys___sigsuspend14(sigmask);
587 	TESTCANCEL(self);
588 
589 	return retval;
590 }
591 
592 int
593 __sigtimedwait50(const sigset_t * __restrict set, siginfo_t * __restrict info,
594     const struct timespec * __restrict timeout)
595 {
596 	pthread_t self;
597 	int retval;
598 	struct timespec tout, *tp;
599 	if (timeout) {
600 		tout = *timeout;
601 		tp = &tout;
602 	} else
603 		tp = NULL;
604 
605 	self = pthread__self();
606 	TESTCANCEL(self);
607 	retval = ____sigtimedwait50(set, info, tp);
608 	TESTCANCEL(self);
609 
610 	return retval;
611 }
612 
613 __strong_alias(_close, close)
614 __strong_alias(_fcntl, fcntl)
615 __strong_alias(_fdatasync, fdatasync)
616 __strong_alias(_fsync, fsync)
617 __weak_alias(fsync_range, _fsync_range)
618 __strong_alias(_mq_send, mq_send)
619 __strong_alias(_mq_receive, mq_receive)
620 __strong_alias(_msgrcv, msgrcv)
621 __strong_alias(_msgsnd, msgsnd)
622 __strong_alias(___msync13, __msync13)
623 __strong_alias(___nanosleep50, __nanosleep50)
624 __strong_alias(_open, open)
625 __strong_alias(_poll, poll)
626 __strong_alias(_pread, pread)
627 __strong_alias(_pwrite, pwrite)
628 __strong_alias(_read, read)
629 __strong_alias(_readv, readv)
630 __strong_alias(_write, write)
631 __strong_alias(_writev, writev)
632 
633 #endif	/* !lint */
634