thr_syscalls.c revision 135301
1/*
2 * Copyright (c) 2000 Jason Evans <jasone@freebsd.org>.
3 * Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org>
4 * Copyright (c) 2003 Jeff Roberson <jeff@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 * $FreeBSD: head/lib/libthr/thread/thr_syscalls.c 135301 2004-09-16 13:55:46Z mtm $
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/cdefs.h>
68#include <sys/fcntl.h>
69#include <sys/mman.h>
70#include <sys/param.h>
71#include <sys/select.h>
72#include <sys/socket.h>
73#include <sys/time.h>
74#include <sys/types.h>
75#include <sys/uio.h>
76#include <sys/wait.h>
77
78#include <aio.h>
79#include <dirent.h>
80#include <errno.h>
81#include <fcntl.h>
82#include <poll.h>
83#include <pthread.h>
84#include <semaphore.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
93#include "thr_private.h"
94
95extern spinlock_t *__malloc_lock;
96
97extern int __creat(const char *, mode_t);
98extern int __sleep(unsigned int);
99extern int __sys_nanosleep(const struct timespec *, struct timespec *);
100extern int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
101extern int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
102extern int __system(const char *);
103extern int __tcdrain(int);
104extern pid_t __wait(int *);
105extern pid_t __sys_wait4(pid_t, int *, int, struct rusage *);
106extern pid_t __waitpid(pid_t, int *, int);
107
108__weak_reference(_accept, accept);
109
110int
111_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
112{
113	int ret;
114
115	_thread_enter_cancellation_point();
116	ret = __sys_accept(s, addr, addrlen);
117	_thread_leave_cancellation_point();
118	return (ret);
119}
120
121__weak_reference(_aio_suspend, aio_suspend);
122
123int
124_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
125    timespec *timeout)
126{
127	int	ret;
128
129	_thread_enter_cancellation_point();
130	ret = __sys_aio_suspend(iocbs, niocb, timeout);
131	_thread_leave_cancellation_point();
132
133	return ret;
134}
135
136__weak_reference(_close, close);
137
138int
139_close(int fd)
140{
141	int	ret;
142
143	_thread_enter_cancellation_point();
144	ret = __sys_close(fd);
145	_thread_leave_cancellation_point();
146
147	return ret;
148}
149
150__weak_reference(_connect, connect);
151
152int
153_connect(int s, const struct sockaddr *n, socklen_t l)
154{
155	int ret;
156
157	_thread_enter_cancellation_point();
158	ret = __sys_connect(s, n, l);
159	_thread_leave_cancellation_point();
160	return ret;
161}
162
163__weak_reference(_creat, creat);
164
165int
166_creat(const char *path, mode_t mode)
167{
168	int	ret;
169
170	_thread_enter_cancellation_point();
171	ret = __creat(path, mode);
172	_thread_leave_cancellation_point();
173
174	return ret;
175}
176
177__weak_reference(_fcntl, fcntl);
178
179int
180_fcntl(int fd, int cmd,...)
181{
182	int	ret;
183	va_list	ap;
184
185	_thread_enter_cancellation_point();
186
187	va_start(ap, cmd);
188	switch (cmd) {
189		case F_DUPFD:
190		case F_SETFD:
191		case F_SETFL:
192			ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
193			break;
194		case F_GETFD:
195		case F_GETFL:
196			ret = __sys_fcntl(fd, cmd);
197			break;
198		default:
199			ret = __sys_fcntl(fd, cmd, va_arg(ap, void *));
200	}
201	va_end(ap);
202
203	_thread_leave_cancellation_point();
204
205	return ret;
206}
207
208__weak_reference(_fork, fork);
209
210int
211_fork(int fd)
212{
213	int	ret;
214	struct pthread_atfork *af;
215
216	_pthread_mutex_lock(&_atfork_mutex);
217
218	/* Run down atfork prepare handlers. */
219	TAILQ_FOREACH_REVERSE(af, &_atfork_list, atfork_head, qe) {
220		if (af->prepare != NULL)
221			af->prepare();
222	}
223
224 	/*
225	 * Fork a new process.
226	 * XXX - The correct way to handle __malloc_lock is to have
227	 *	 the threads libraries (or libc) install fork handlers for it
228	 *	 in their initialization routine. We should probably
229	 *	 do that for all the locks in libc.
230	 */
231	if (__isthreaded && __malloc_lock != NULL)
232		_SPINLOCK(__malloc_lock);
233	ret = __sys_fork();
234 	if (ret == 0) {
235		__isthreaded = 0;
236		if (__malloc_lock != NULL)
237			memset(__malloc_lock, 0, sizeof(spinlock_t));
238		init_tdlist(curthread, 1);
239		init_td_common(curthread, NULL, 1);
240		_mutex_reinit(&_atfork_mutex);
241
242		/* Run down atfork child handlers. */
243		TAILQ_FOREACH(af, &_atfork_list, qe) {
244			if (af->child != NULL)
245				af->child();
246		}
247 	} else if (ret != -1) {
248		/* Run down atfork parent handlers. */
249		TAILQ_FOREACH(af, &_atfork_list, qe) {
250			if (af->parent != NULL)
251			af->parent();
252		}
253	}
254
255	if (ret != 0) {
256		if (__isthreaded && __malloc_lock != NULL)
257			_SPINUNLOCK(__malloc_lock);
258		_pthread_mutex_unlock(&_atfork_mutex);
259	}
260	return ret;
261}
262
263
264__weak_reference(_fsync, fsync);
265
266int
267_fsync(int fd)
268{
269	int	ret;
270
271	_thread_enter_cancellation_point();
272	ret = __sys_fsync(fd);
273	_thread_leave_cancellation_point();
274
275	return ret;
276}
277
278__weak_reference(_msgrcv, msgrcv);
279
280int
281_msgrcv(int id, void *p, size_t sz, long t, int f)
282{
283	int ret;
284
285	_thread_enter_cancellation_point();
286	ret = __sys_msgrcv(id, p, sz, t, f);
287	_thread_leave_cancellation_point();
288	return ret;
289}
290
291__weak_reference(_msgsnd, msgsnd);
292
293int
294_msgsnd(int id, const void *p, size_t sz, int f)
295{
296	int ret;
297
298	_thread_enter_cancellation_point();
299	ret = __sys_msgsnd(id, p, sz, f);
300	_thread_leave_cancellation_point();
301	return ret;
302}
303
304__weak_reference(_msync, msync);
305
306int
307_msync(void *addr, size_t len, int flags)
308{
309	int	ret;
310
311	_thread_enter_cancellation_point();
312	ret = __sys_msync(addr, len, flags);
313	_thread_leave_cancellation_point();
314
315	return ret;
316}
317
318__weak_reference(_nanosleep, nanosleep);
319
320int
321_nanosleep(const struct timespec * time_to_sleep, struct timespec *
322    time_remaining)
323{
324	int	ret;
325
326	_thread_enter_cancellation_point();
327	ret = __sys_nanosleep(time_to_sleep, time_remaining);
328	_thread_leave_cancellation_point();
329
330	return ret;
331}
332
333__weak_reference(_open, open);
334
335int
336_open(const char *path, int flags,...)
337{
338	int	ret;
339	int	mode = 0;
340	va_list	ap;
341
342	_thread_enter_cancellation_point();
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	_thread_leave_cancellation_point();
354
355	return ret;
356}
357
358/*
359 * The implementation in libc calls sigpause(), which is also
360 * a cancellation point.
361 */
362#if 0
363__weak_reference(_pause, pause);
364
365int
366_pause(void)
367{
368	_thread_enter_cancellation_point();
369	__pause();
370	_thread_leave_cancellation_point();
371}
372#endif
373
374__weak_reference(_poll, poll);
375
376int
377_poll(struct pollfd *fds, unsigned int nfds, int timeout)
378{
379	int ret;
380
381	_thread_enter_cancellation_point();
382	ret = __sys_poll(fds, nfds, timeout);
383	_thread_leave_cancellation_point();
384
385	return ret;
386}
387
388/* XXXFix */
389#if 0
390__weak_reference(_pread, pread);
391
392ssize_t
393_pread(int d, void *b, size_t n, off_t o)
394{
395	ssize_t ret;
396
397	_thread_enter_cancellation_point();
398	ret = __sys_pread(d, b, n, o);
399	_thread_leave_cancellation_point();
400	return (ret);
401}
402#endif
403
404/* The libc version calls select(), which is also a cancellation point. */
405#if 0
406extern int __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
407		const struct timespec *timo, const sigset_t *mask);
408
409int
410pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
411	const struct timespec *timo, const sigset_t *mask)
412{
413	int ret;
414
415	_thread_enter_cancellation_point();
416	ret = __pselect(count, rfds, wfds, efds, timo, mask);
417	_thread_leave_cancellation_point();
418
419	return (ret);
420}
421#endif
422
423/* XXXFix */
424#if 0
425__weak_reference(_pwrite, pwrite);
426
427ssize_t
428_pwrite(int d, const void *b, size_t n, off_t o)
429{
430	ssize_t ret;
431
432	_thread_enter_cancellation_point();
433	ret = __sys_pwrite(d, b, n, o);
434	_thread_leave_cancellation_point();
435	return (ret);
436}
437#endif
438
439__weak_reference(_raise, raise);
440
441int
442_raise(int sig)
443{
444	int error;
445
446	error = pthread_kill(pthread_self(), sig);
447	if (error != 0) {
448		errno = error;
449		error = -1;
450	}
451	return (error);
452}
453
454__weak_reference(_read, read);
455
456ssize_t
457_read(int fd, void *buf, size_t nbytes)
458{
459	ssize_t	ret;
460
461	_thread_enter_cancellation_point();
462	ret = __sys_read(fd, buf, nbytes);
463	_thread_leave_cancellation_point();
464
465	return ret;
466}
467
468__weak_reference(_readv, readv);
469
470ssize_t
471_readv(int fd, const struct iovec *iov, int iovcnt)
472{
473	ssize_t ret;
474
475	_thread_enter_cancellation_point();
476	ret = __sys_readv(fd, iov, iovcnt);
477	_thread_leave_cancellation_point();
478
479	return ret;
480}
481
482/*
483 * The libc implementation of recv() calls recvfrom, which
484 * is also a cancellation point.
485 */
486#if 0
487__weak_reference(_recv, recv);
488
489ssize_t
490_recv(int s, void *b, size_t l, int f)
491{
492	ssize_t ret;
493
494	_thread_enter_cancellation_point();
495	ret = __sys_recv(s, b, l, f);
496	_thread_leave_cancellation_point();
497	return (ret);
498}
499#endif
500
501__weak_reference(_recvfrom, recvfrom);
502
503ssize_t
504_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from,
505    socklen_t *fl)
506{
507	ssize_t ret;
508
509	_thread_enter_cancellation_point();
510	ret = __sys_recvfrom(s, b, l, f, from, fl);
511	_thread_leave_cancellation_point();
512	return (ret);
513}
514
515__weak_reference(_recvmsg, recvmsg);
516
517ssize_t
518_recvmsg(int s, struct msghdr *m, int f)
519{
520	ssize_t ret;
521
522	_thread_enter_cancellation_point();
523	ret = __sys_recvmsg(s, m, f);
524	_thread_leave_cancellation_point();
525	return (ret);
526}
527
528__weak_reference(_select, select);
529
530int
531_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
532	struct timeval *timeout)
533{
534	int ret;
535
536	_thread_enter_cancellation_point();
537	ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
538	_thread_leave_cancellation_point();
539
540	return ret;
541}
542
543/*
544 * Libc implements this by calling _sendto(), which is also a
545 * cancellation point.
546 */
547#if 0
548__weak_reference(_send, send);
549
550ssize_t
551_send(int s, const void *m, size_t l, int f)
552{
553	ssize_t ret;
554
555	_thread_enter_cancellation_point();
556	ret = _sendto(s, m, l, f, NULL, 0);
557	_thread_leave_cancellation_point();
558	return (ret);
559}
560#endif
561
562__weak_reference(_sendmsg, sendmsg);
563
564ssize_t
565_sendmsg(int s, const struct msghdr *m, int f)
566{
567	ssize_t ret;
568
569	_thread_enter_cancellation_point();
570	ret = __sys_sendmsg(s, m, f);
571	_thread_leave_cancellation_point();
572	return (ret);
573}
574
575__weak_reference(_sendto, sendto);
576
577ssize_t
578_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t,
579    socklen_t tl)
580{
581	ssize_t ret;
582
583	_thread_enter_cancellation_point();
584	ret = __sys_sendto(s, m, l, f, t, tl);
585	_thread_leave_cancellation_point();
586	return (ret);
587}
588
589/*
590 * The implementation in libc calls sigsuspend(), which is also
591 * a cancellation point.
592 */
593#if 0
594__weak_reference(_sigpause, sigpause);
595
596int
597_sigpause(int m)
598{
599	int ret;
600
601	_thread_enter_cancellation_point();
602	ret = __sys_sigpause(m);
603	_thread_leave_cancellation_point();
604	return (ret);
605}
606#endif
607
608__weak_reference(_sigsuspend, sigsuspend);
609
610int
611_sigsuspend(const sigset_t *m)
612{
613	int ret;
614
615	_thread_enter_cancellation_point();
616	ret = __sys_sigsuspend(m);
617	_thread_leave_cancellation_point();
618	return (ret);
619}
620
621__weak_reference(_sigtimedwait, sigtimedwait);
622
623int
624_sigtimedwait(const sigset_t *s, siginfo_t *i, const struct timespec *t)
625{
626	int ret;
627
628	_thread_enter_cancellation_point();
629	ret = __sys_sigtimedwait(s, i, t);
630	_thread_leave_cancellation_point();
631	return (ret);
632}
633
634__weak_reference(_sigwait, sigwait);
635
636int
637_sigwait(const sigset_t *s, int *i)
638{
639	int ret;
640
641	_thread_enter_cancellation_point();
642	ret = __sys_sigwait(s, i);
643	_thread_leave_cancellation_point();
644	return (ret);
645}
646
647__weak_reference(_sigwaitinfo, sigwaitinfo);
648
649int
650_sigwaitinfo(const sigset_t *s, siginfo_t *i)
651{
652	int ret;
653
654	_thread_enter_cancellation_point();
655	ret = __sys_sigwaitinfo(s, i);
656	_thread_leave_cancellation_point();
657	return (ret);
658}
659
660__weak_reference(_sleep, sleep);
661
662unsigned int
663_sleep(unsigned int seconds)
664{
665	unsigned int	ret;
666
667	_thread_enter_cancellation_point();
668	ret = __sleep(seconds);
669	_thread_leave_cancellation_point();
670
671	return ret;
672}
673
674__weak_reference(_system, system);
675
676int
677_system(const char *string)
678{
679	int	ret;
680
681	_thread_enter_cancellation_point();
682	ret = __system(string);
683	_thread_leave_cancellation_point();
684
685	return ret;
686}
687
688
689__weak_reference(_tcdrain, tcdrain);
690
691int
692_tcdrain(int fd)
693{
694	int	ret;
695
696	_thread_enter_cancellation_point();
697	ret = __tcdrain(fd);
698	_thread_leave_cancellation_point();
699
700	return ret;
701}
702
703/*
704 * The usleep() implementation calls nanosleep(), which is also
705 * a cancellation point.
706 */
707#if 0
708__weak_reference(_usleep, usleep);
709
710int
711_usleep(useconds_t u)
712{
713	int ret;
714
715	_thread_enter_cancellation_point();
716	ret = __sys_usleep(u);
717	_thread_leave_cancellation_point();
718	return (ret);
719}
720#endif
721
722__weak_reference(_wait, wait);
723
724pid_t
725_wait(int *istat)
726{
727	pid_t	ret;
728
729	_thread_enter_cancellation_point();
730	ret = __wait(istat);
731	_thread_leave_cancellation_point();
732
733	return ret;
734}
735
736__weak_reference(_wait4, wait4);
737
738pid_t
739_wait4(pid_t pid, int *istat, int options, struct rusage *rusage)
740{
741	pid_t ret;
742
743	_thread_enter_cancellation_point();
744	ret = __sys_wait4(pid, istat, options, rusage);
745	_thread_leave_cancellation_point();
746
747	return ret;
748}
749
750/*
751 * The libc implementation of waitpid calls wait4().
752 */
753#if 0
754__weak_reference(_waitpid, waitpid);
755
756pid_t
757_waitpid(pid_t wpid, int *status, int options)
758{
759	pid_t	ret;
760
761	_thread_enter_cancellation_point();
762	ret = __waitpid(wpid, status, options);
763	_thread_leave_cancellation_point();
764
765	return ret;
766}
767#endif
768
769__weak_reference(_write, write);
770
771ssize_t
772_write(int fd, const void *buf, size_t nbytes)
773{
774	ssize_t	ret;
775
776	_thread_enter_cancellation_point();
777	ret = __sys_write(fd, buf, nbytes);
778	_thread_leave_cancellation_point();
779
780	return ret;
781}
782
783__weak_reference(_writev, writev);
784
785ssize_t
786_writev(int fd, const struct iovec *iov, int iovcnt)
787{
788	ssize_t ret;
789
790	_thread_enter_cancellation_point();
791	ret = __sys_writev(fd, iov, iovcnt);
792	_thread_leave_cancellation_point();
793
794	return ret;
795}
796