xref: /illumos-gate/usr/src/lib/libc/port/threads/scalls.c (revision fca543ca45b12c44a243625bce68b645ba8ed791)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
534709573Sraf  * Common Development and Distribution License (the "License").
634709573Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
210293487cSraf 
227c478bd9Sstevel@tonic-gate /*
238fd04b83SRoger A. Faulkner  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*fca543caSDJ Hoffman  * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
285dbfd19aSTheo Schlossnagle /* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
295dbfd19aSTheo Schlossnagle 
307c478bd9Sstevel@tonic-gate #include "lint.h"
317c478bd9Sstevel@tonic-gate #include "thr_uberdata.h"
327c478bd9Sstevel@tonic-gate #include <stdarg.h>
337c478bd9Sstevel@tonic-gate #include <poll.h>
347c478bd9Sstevel@tonic-gate #include <stropts.h>
357c478bd9Sstevel@tonic-gate #include <dlfcn.h>
36a574db85Sraf #include <wait.h>
37a574db85Sraf #include <sys/socket.h>
387c478bd9Sstevel@tonic-gate #include <sys/uio.h>
39a574db85Sraf #include <sys/file.h>
40a574db85Sraf #include <sys/door.h>
417c478bd9Sstevel@tonic-gate 
427257d1b4Sraf /*
437257d1b4Sraf  * These leading-underbar symbols exist because mistakes were made
447257d1b4Sraf  * in the past that put them into non-SUNWprivate versions of
457257d1b4Sraf  * the libc mapfiles.  They should be eliminated, but oh well...
467257d1b4Sraf  */
477257d1b4Sraf #pragma weak _fork = fork
487257d1b4Sraf #pragma weak _read = read
497257d1b4Sraf #pragma weak _write = write
507257d1b4Sraf #pragma weak _getmsg = getmsg
517257d1b4Sraf #pragma weak _getpmsg = getpmsg
527257d1b4Sraf #pragma weak _putmsg = putmsg
537257d1b4Sraf #pragma weak _putpmsg = putpmsg
547257d1b4Sraf #pragma weak _sleep = sleep
557257d1b4Sraf #pragma weak _close = close
567257d1b4Sraf #pragma weak _creat = creat
577257d1b4Sraf #pragma weak _fcntl = fcntl
587257d1b4Sraf #pragma weak _fsync = fsync
597257d1b4Sraf #pragma weak _lockf = lockf
607257d1b4Sraf #pragma weak _msgrcv = msgrcv
617257d1b4Sraf #pragma weak _msgsnd = msgsnd
627257d1b4Sraf #pragma weak _msync = msync
637257d1b4Sraf #pragma weak _open = open
647257d1b4Sraf #pragma weak _openat = openat
657257d1b4Sraf #pragma weak _pause = pause
667257d1b4Sraf #pragma weak _readv = readv
677257d1b4Sraf #pragma weak _sigpause = sigpause
687257d1b4Sraf #pragma weak _sigsuspend = sigsuspend
697257d1b4Sraf #pragma weak _tcdrain = tcdrain
707257d1b4Sraf #pragma weak _waitid = waitid
717257d1b4Sraf #pragma weak _writev = writev
727257d1b4Sraf 
737257d1b4Sraf #if !defined(_LP64)
747257d1b4Sraf #pragma weak _creat64 = creat64
757257d1b4Sraf #pragma weak _lockf64 = lockf64
767257d1b4Sraf #pragma weak _open64 = open64
777257d1b4Sraf #pragma weak _openat64 = openat64
787257d1b4Sraf #pragma weak _pread64 = pread64
797257d1b4Sraf #pragma weak _pwrite64 = pwrite64
807257d1b4Sraf #endif
817257d1b4Sraf 
82d56c62ccSraf /*
83d56c62ccSraf  * These are SUNWprivate, but they are being used by Sun Studio libcollector.
84d56c62ccSraf  */
85d56c62ccSraf #pragma weak _fork1 = fork1
86d56c62ccSraf #pragma weak _forkall = forkall
87d56c62ccSraf 
887c478bd9Sstevel@tonic-gate /*
8998c1a6b4Sraf  * atfork_lock protects the pthread_atfork() data structures.
9098c1a6b4Sraf  *
91b6233ca5Sraf  * fork_lock does double-duty.  Not only does it (and atfork_lock)
92b6233ca5Sraf  * serialize calls to fork() and forkall(), but it also serializes calls
93b6233ca5Sraf  * to thr_suspend() and thr_continue() (because fork() and forkall() also
94b6233ca5Sraf  * suspend and continue other threads and they want no competition).
95b6233ca5Sraf  *
9698c1a6b4Sraf  * Functions called in dlopen()ed L10N objects can do anything, including
9798c1a6b4Sraf  * call malloc() and free().  Such calls are not fork-safe when protected
9898c1a6b4Sraf  * by an ordinary mutex that is acquired in libc's prefork processing
9998c1a6b4Sraf  * because, with an interposed malloc library present, there would be a
10098c1a6b4Sraf  * lock ordering violation due to the pthread_atfork() prefork function
10198c1a6b4Sraf  * in the interposition library acquiring its malloc lock(s) before the
102b6233ca5Sraf  * ordinary mutex in libc being acquired by libc's prefork functions.
103b6233ca5Sraf  *
10498c1a6b4Sraf  * Within libc, calls to malloc() and free() are fork-safe if the calls
10598c1a6b4Sraf  * are made while holding no other libc locks.  This covers almost all
10698c1a6b4Sraf  * of libc's malloc() and free() calls.  For those libc code paths, such
10798c1a6b4Sraf  * as the above-mentioned L10N calls, that require serialization and that
10898c1a6b4Sraf  * may call malloc() or free(), libc uses callout_lock_enter() to perform
10998c1a6b4Sraf  * the serialization.  This works because callout_lock is not acquired as
11098c1a6b4Sraf  * part of running the pthread_atfork() prefork handlers (to avoid the
11198c1a6b4Sraf  * lock ordering violation described above).  Rather, it is simply
11298c1a6b4Sraf  * reinitialized in postfork1_child() to cover the case that some
11398c1a6b4Sraf  * now-defunct thread might have been suspended while holding it.
1147c478bd9Sstevel@tonic-gate  */
115b6233ca5Sraf 
1162e145884Sraf void
1172e145884Sraf fork_lock_enter(void)
1187c478bd9Sstevel@tonic-gate {
119b6233ca5Sraf 	ASSERT(curthread->ul_critical == 0);
1208cd45542Sraf 	(void) mutex_lock(&curthread->ul_uberdata->fork_lock);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate void
1247c478bd9Sstevel@tonic-gate fork_lock_exit(void)
1257c478bd9Sstevel@tonic-gate {
126b6233ca5Sraf 	ASSERT(curthread->ul_critical == 0);
1278cd45542Sraf 	(void) mutex_unlock(&curthread->ul_uberdata->fork_lock);
128b6233ca5Sraf }
129b6233ca5Sraf 
130a574db85Sraf /*
131a574db85Sraf  * Use cancel_safe_mutex_lock() to protect against being cancelled while
132a574db85Sraf  * holding callout_lock and calling outside of libc (via L10N plugins).
133a574db85Sraf  * We will honor a pending cancellation request when callout_lock_exit()
134a574db85Sraf  * is called, by calling cancel_safe_mutex_unlock().
135a574db85Sraf  */
136b6233ca5Sraf void
13798c1a6b4Sraf callout_lock_enter(void)
138b6233ca5Sraf {
139b6233ca5Sraf 	ASSERT(curthread->ul_critical == 0);
140a574db85Sraf 	cancel_safe_mutex_lock(&curthread->ul_uberdata->callout_lock);
141b6233ca5Sraf }
1427c478bd9Sstevel@tonic-gate 
143b6233ca5Sraf void
14498c1a6b4Sraf callout_lock_exit(void)
145b6233ca5Sraf {
146b6233ca5Sraf 	ASSERT(curthread->ul_critical == 0);
147a574db85Sraf 	cancel_safe_mutex_unlock(&curthread->ul_uberdata->callout_lock);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
150dfb96a4fSab pid_t
1517257d1b4Sraf forkx(int flags)
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate 	ulwp_t *self = curthread;
1547c478bd9Sstevel@tonic-gate 	uberdata_t *udp = self->ul_uberdata;
1557c478bd9Sstevel@tonic-gate 	pid_t pid;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	if (self->ul_vfork) {
1587c478bd9Sstevel@tonic-gate 		/*
1597c478bd9Sstevel@tonic-gate 		 * We are a child of vfork(); omit all of the fork
1607c478bd9Sstevel@tonic-gate 		 * logic and go straight to the system call trap.
1617c478bd9Sstevel@tonic-gate 		 * A vfork() child of a multithreaded parent
1627c478bd9Sstevel@tonic-gate 		 * must never call fork().
1637c478bd9Sstevel@tonic-gate 		 */
1647c478bd9Sstevel@tonic-gate 		if (udp->uberflags.uf_mt) {
1657c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
1667c478bd9Sstevel@tonic-gate 			return (-1);
1677c478bd9Sstevel@tonic-gate 		}
168657b1f3dSraf 		pid = __forkx(flags);
1697c478bd9Sstevel@tonic-gate 		if (pid == 0) {		/* child */
1708cd45542Sraf 			udp->pid = getpid();
1717c478bd9Sstevel@tonic-gate 			self->ul_vfork = 0;
1727c478bd9Sstevel@tonic-gate 		}
1737c478bd9Sstevel@tonic-gate 		return (pid);
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 
1762e145884Sraf 	sigoff(self);
1772e145884Sraf 	if (self->ul_fork) {
1787c478bd9Sstevel@tonic-gate 		/*
1797c478bd9Sstevel@tonic-gate 		 * Cannot call fork() from a fork handler.
1807c478bd9Sstevel@tonic-gate 		 */
1812e145884Sraf 		sigon(self);
1822e145884Sraf 		errno = EDEADLK;
1837c478bd9Sstevel@tonic-gate 		return (-1);
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 	self->ul_fork = 1;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/*
1887c478bd9Sstevel@tonic-gate 	 * The functions registered by pthread_atfork() are defined by
1897c478bd9Sstevel@tonic-gate 	 * the application and its libraries and we must not hold any
1902e145884Sraf 	 * internal lmutex_lock()-acquired locks while invoking them.
1912e145884Sraf 	 * We hold only udp->atfork_lock to protect the atfork linkages.
1922e145884Sraf 	 * If one of these pthread_atfork() functions attempts to fork
193b6233ca5Sraf 	 * or to call pthread_atfork(), libc will detect the error and
194b6233ca5Sraf 	 * fail the call with EDEADLK.  Otherwise, the pthread_atfork()
195b6233ca5Sraf 	 * functions are free to do anything they please (except they
196b6233ca5Sraf 	 * will not receive any signals).
1977c478bd9Sstevel@tonic-gate 	 */
1988cd45542Sraf 	(void) mutex_lock(&udp->atfork_lock);
1993771f298SRoger A. Faulkner 
2003771f298SRoger A. Faulkner 	/*
2013771f298SRoger A. Faulkner 	 * Posix (SUSv3) requires fork() to be async-signal-safe.
2023771f298SRoger A. Faulkner 	 * This cannot be made to happen with fork handlers in place
2033771f298SRoger A. Faulkner 	 * (they grab locks).  To be in nominal compliance, don't run
2043771f298SRoger A. Faulkner 	 * any fork handlers if we are called within a signal context.
2053771f298SRoger A. Faulkner 	 * This leaves the child process in a questionable state with
2063771f298SRoger A. Faulkner 	 * respect to its locks, but at least the parent process does
2073771f298SRoger A. Faulkner 	 * not become deadlocked due to the calling thread attempting
2083771f298SRoger A. Faulkner 	 * to acquire a lock that it already owns.
2093771f298SRoger A. Faulkner 	 */
2103771f298SRoger A. Faulkner 	if (self->ul_siglink == NULL)
2113771f298SRoger A. Faulkner 		_prefork_handler();
2127c478bd9Sstevel@tonic-gate 
2132e145884Sraf 	/*
2142e145884Sraf 	 * Block every other thread attempting thr_suspend() or thr_continue().
2152e145884Sraf 	 */
2168cd45542Sraf 	(void) mutex_lock(&udp->fork_lock);
2172e145884Sraf 
2187c478bd9Sstevel@tonic-gate 	/*
2197c478bd9Sstevel@tonic-gate 	 * Block all signals.
2202e145884Sraf 	 * Just deferring them via sigoff() is not enough.
2217c478bd9Sstevel@tonic-gate 	 * We have to avoid taking a deferred signal in the child
222657b1f3dSraf 	 * that was actually sent to the parent before __forkx().
2237c478bd9Sstevel@tonic-gate 	 */
2247c478bd9Sstevel@tonic-gate 	block_all_signals(self);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	/*
2277c478bd9Sstevel@tonic-gate 	 * This suspends all threads but this one, leaving them
2287c478bd9Sstevel@tonic-gate 	 * suspended outside of any critical regions in the library.
229b6233ca5Sraf 	 * Thus, we are assured that no lmutex_lock()-acquired library
230b6233ca5Sraf 	 * locks are held while we invoke fork() from the current thread.
2317c478bd9Sstevel@tonic-gate 	 */
2327c478bd9Sstevel@tonic-gate 	suspend_fork();
2337c478bd9Sstevel@tonic-gate 
234657b1f3dSraf 	pid = __forkx(flags);
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	if (pid == 0) {		/* child */
2377c478bd9Sstevel@tonic-gate 		/*
2387c478bd9Sstevel@tonic-gate 		 * Clear our schedctl pointer.
2397c478bd9Sstevel@tonic-gate 		 * Discard any deferred signal that was sent to the parent.
240657b1f3dSraf 		 * Because we blocked all signals before __forkx(), a
2417c478bd9Sstevel@tonic-gate 		 * deferred signal cannot have been taken by the child.
2427c478bd9Sstevel@tonic-gate 		 */
2437c478bd9Sstevel@tonic-gate 		self->ul_schedctl_called = NULL;
2447c478bd9Sstevel@tonic-gate 		self->ul_schedctl = NULL;
2457c478bd9Sstevel@tonic-gate 		self->ul_cursig = 0;
2467c478bd9Sstevel@tonic-gate 		self->ul_siginfo.si_signo = 0;
2478cd45542Sraf 		udp->pid = getpid();
2487c478bd9Sstevel@tonic-gate 		/* reset the library's data structures to reflect one thread */
249c242ec1bSRoger A. Faulkner 		unregister_locks();
250f841f6adSraf 		postfork1_child();
2517c478bd9Sstevel@tonic-gate 		restore_signals(self);
2528cd45542Sraf 		(void) mutex_unlock(&udp->fork_lock);
2533771f298SRoger A. Faulkner 		if (self->ul_siglink == NULL)
2543771f298SRoger A. Faulkner 			_postfork_child_handler();
2557c478bd9Sstevel@tonic-gate 	} else {
256657b1f3dSraf 		/* restart all threads that were suspended for fork() */
2577c478bd9Sstevel@tonic-gate 		continue_fork(0);
2587c478bd9Sstevel@tonic-gate 		restore_signals(self);
2598cd45542Sraf 		(void) mutex_unlock(&udp->fork_lock);
2603771f298SRoger A. Faulkner 		if (self->ul_siglink == NULL)
2613771f298SRoger A. Faulkner 			_postfork_parent_handler();
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 
2648cd45542Sraf 	(void) mutex_unlock(&udp->atfork_lock);
2657c478bd9Sstevel@tonic-gate 	self->ul_fork = 0;
2662e145884Sraf 	sigon(self);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	return (pid);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate /*
272657b1f3dSraf  * fork() is fork1() for both Posix threads and Solaris threads.
273657b1f3dSraf  * The forkall() interface exists for applications that require
274657b1f3dSraf  * the semantics of replicating all threads.
2757c478bd9Sstevel@tonic-gate  */
2767257d1b4Sraf #pragma weak fork1 = fork
2777c478bd9Sstevel@tonic-gate pid_t
2787257d1b4Sraf fork(void)
279657b1f3dSraf {
2807257d1b4Sraf 	return (forkx(0));
281657b1f3dSraf }
282657b1f3dSraf 
283657b1f3dSraf /*
284657b1f3dSraf  * Much of the logic here is the same as in forkx().
285657b1f3dSraf  * See the comments in forkx(), above.
286657b1f3dSraf  */
287dfb96a4fSab pid_t
2887257d1b4Sraf forkallx(int flags)
2897c478bd9Sstevel@tonic-gate {
2907c478bd9Sstevel@tonic-gate 	ulwp_t *self = curthread;
2917c478bd9Sstevel@tonic-gate 	uberdata_t *udp = self->ul_uberdata;
2927c478bd9Sstevel@tonic-gate 	pid_t pid;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	if (self->ul_vfork) {
2957c478bd9Sstevel@tonic-gate 		if (udp->uberflags.uf_mt) {
2967c478bd9Sstevel@tonic-gate 			errno = ENOTSUP;
2977c478bd9Sstevel@tonic-gate 			return (-1);
2987c478bd9Sstevel@tonic-gate 		}
299657b1f3dSraf 		pid = __forkallx(flags);
3007c478bd9Sstevel@tonic-gate 		if (pid == 0) {		/* child */
3018cd45542Sraf 			udp->pid = getpid();
3027c478bd9Sstevel@tonic-gate 			self->ul_vfork = 0;
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 		return (pid);
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
3072e145884Sraf 	sigoff(self);
3082e145884Sraf 	if (self->ul_fork) {
3092e145884Sraf 		sigon(self);
3102e145884Sraf 		errno = EDEADLK;
3117c478bd9Sstevel@tonic-gate 		return (-1);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 	self->ul_fork = 1;
3148cd45542Sraf 	(void) mutex_lock(&udp->atfork_lock);
3158cd45542Sraf 	(void) mutex_lock(&udp->fork_lock);
3167c478bd9Sstevel@tonic-gate 	block_all_signals(self);
3177c478bd9Sstevel@tonic-gate 	suspend_fork();
3187c478bd9Sstevel@tonic-gate 
319657b1f3dSraf 	pid = __forkallx(flags);
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	if (pid == 0) {
3227c478bd9Sstevel@tonic-gate 		self->ul_schedctl_called = NULL;
3237c478bd9Sstevel@tonic-gate 		self->ul_schedctl = NULL;
3247c478bd9Sstevel@tonic-gate 		self->ul_cursig = 0;
3257c478bd9Sstevel@tonic-gate 		self->ul_siginfo.si_signo = 0;
3268cd45542Sraf 		udp->pid = getpid();
327c242ec1bSRoger A. Faulkner 		unregister_locks();
3287c478bd9Sstevel@tonic-gate 		continue_fork(1);
3297c478bd9Sstevel@tonic-gate 	} else {
3307c478bd9Sstevel@tonic-gate 		continue_fork(0);
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 	restore_signals(self);
3338cd45542Sraf 	(void) mutex_unlock(&udp->fork_lock);
3348cd45542Sraf 	(void) mutex_unlock(&udp->atfork_lock);
3352e145884Sraf 	self->ul_fork = 0;
3362e145884Sraf 	sigon(self);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	return (pid);
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate 
341657b1f3dSraf pid_t
3427257d1b4Sraf forkall(void)
343657b1f3dSraf {
3447257d1b4Sraf 	return (forkallx(0));
345657b1f3dSraf }
346657b1f3dSraf 
3477c478bd9Sstevel@tonic-gate /*
348a574db85Sraf  * For the implementation of cancellation at cancellation points.
3497c478bd9Sstevel@tonic-gate  */
3507c478bd9Sstevel@tonic-gate #define	PROLOGUE							\
3517c478bd9Sstevel@tonic-gate {									\
3527c478bd9Sstevel@tonic-gate 	ulwp_t *self = curthread;					\
353a574db85Sraf 	int nocancel =							\
354a574db85Sraf 	    (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks |	\
355a574db85Sraf 	    self->ul_critical | self->ul_sigdefer);			\
356a574db85Sraf 	int abort = 0;							\
3577c478bd9Sstevel@tonic-gate 	if (nocancel == 0) {						\
3587c478bd9Sstevel@tonic-gate 		self->ul_save_async = self->ul_cancel_async;		\
3597c478bd9Sstevel@tonic-gate 		if (!self->ul_cancel_disabled) {			\
3607c478bd9Sstevel@tonic-gate 			self->ul_cancel_async = 1;			\
3617c478bd9Sstevel@tonic-gate 			if (self->ul_cancel_pending)			\
3627257d1b4Sraf 				pthread_exit(PTHREAD_CANCELED);		\
3637c478bd9Sstevel@tonic-gate 		}							\
3647c478bd9Sstevel@tonic-gate 		self->ul_sp = stkptr();					\
365a574db85Sraf 	} else if (self->ul_cancel_pending &&				\
366a574db85Sraf 	    !self->ul_cancel_disabled) {				\
367a574db85Sraf 		set_cancel_eintr_flag(self);				\
368a574db85Sraf 		abort = 1;						\
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate #define	EPILOGUE							\
3727c478bd9Sstevel@tonic-gate 	if (nocancel == 0) {						\
3737c478bd9Sstevel@tonic-gate 		self->ul_sp = 0;					\
3747c478bd9Sstevel@tonic-gate 		self->ul_cancel_async = self->ul_save_async;		\
3757c478bd9Sstevel@tonic-gate 	}								\
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate /*
3797c478bd9Sstevel@tonic-gate  * Perform the body of the action required by most of the cancelable
3807c478bd9Sstevel@tonic-gate  * function calls.  The return(function_call) part is to allow the
3817c478bd9Sstevel@tonic-gate  * compiler to make the call be executed with tail recursion, which
3827c478bd9Sstevel@tonic-gate  * saves a register window on sparc and slightly (not much) improves
3837c478bd9Sstevel@tonic-gate  * the code for x86/x64 compilations.
3847c478bd9Sstevel@tonic-gate  */
3857c478bd9Sstevel@tonic-gate #define	PERFORM(function_call)						\
3867c478bd9Sstevel@tonic-gate 	PROLOGUE							\
387a574db85Sraf 	if (abort) {							\
388a574db85Sraf 		*self->ul_errnop = EINTR;				\
389a574db85Sraf 		return (-1);						\
390a574db85Sraf 	}								\
3917c478bd9Sstevel@tonic-gate 	if (nocancel)							\
3927c478bd9Sstevel@tonic-gate 		return (function_call);					\
3937c478bd9Sstevel@tonic-gate 	rv = function_call;						\
3947c478bd9Sstevel@tonic-gate 	EPILOGUE							\
3957c478bd9Sstevel@tonic-gate 	return (rv);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate  * Specialized prologue for sigsuspend() and pollsys().
3997c478bd9Sstevel@tonic-gate  * These system calls pass a signal mask to the kernel.
4007c478bd9Sstevel@tonic-gate  * The kernel replaces the thread's signal mask with the
4017c478bd9Sstevel@tonic-gate  * temporary mask before the thread goes to sleep.  If
4027c478bd9Sstevel@tonic-gate  * a signal is received, the signal handler will execute
4037c478bd9Sstevel@tonic-gate  * with the temporary mask, as modified by the sigaction
4047c478bd9Sstevel@tonic-gate  * for the particular signal.
4057c478bd9Sstevel@tonic-gate  *
4067c478bd9Sstevel@tonic-gate  * We block all signals until we reach the kernel with the
4077c478bd9Sstevel@tonic-gate  * temporary mask.  This eliminates race conditions with
4087c478bd9Sstevel@tonic-gate  * setting the signal mask while signals are being posted.
4097c478bd9Sstevel@tonic-gate  */
4107c478bd9Sstevel@tonic-gate #define	PROLOGUE_MASK(sigmask)						\
4117c478bd9Sstevel@tonic-gate {									\
4127c478bd9Sstevel@tonic-gate 	ulwp_t *self = curthread;					\
413a574db85Sraf 	int nocancel =							\
414a574db85Sraf 	    (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks |	\
415a574db85Sraf 	    self->ul_critical | self->ul_sigdefer);			\
4167c478bd9Sstevel@tonic-gate 	if (!self->ul_vfork) {						\
4177c478bd9Sstevel@tonic-gate 		if (sigmask) {						\
4187c478bd9Sstevel@tonic-gate 			block_all_signals(self);			\
419bdf0047cSRoger A. Faulkner 			self->ul_tmpmask = *sigmask;			\
4207c478bd9Sstevel@tonic-gate 			delete_reserved_signals(&self->ul_tmpmask);	\
4217c478bd9Sstevel@tonic-gate 			self->ul_sigsuspend = 1;			\
4227c478bd9Sstevel@tonic-gate 		}							\
4237c478bd9Sstevel@tonic-gate 		if (nocancel == 0) {					\
4247c478bd9Sstevel@tonic-gate 			self->ul_save_async = self->ul_cancel_async;	\
4257c478bd9Sstevel@tonic-gate 			if (!self->ul_cancel_disabled) {		\
4267c478bd9Sstevel@tonic-gate 				self->ul_cancel_async = 1;		\
4277c478bd9Sstevel@tonic-gate 				if (self->ul_cancel_pending) {		\
4287c478bd9Sstevel@tonic-gate 					if (self->ul_sigsuspend) {	\
4297c478bd9Sstevel@tonic-gate 						self->ul_sigsuspend = 0;\
4307c478bd9Sstevel@tonic-gate 						restore_signals(self);	\
4317c478bd9Sstevel@tonic-gate 					}				\
4327257d1b4Sraf 					pthread_exit(PTHREAD_CANCELED);	\
4337c478bd9Sstevel@tonic-gate 				}					\
4347c478bd9Sstevel@tonic-gate 			}						\
4357c478bd9Sstevel@tonic-gate 			self->ul_sp = stkptr();				\
4367c478bd9Sstevel@tonic-gate 		}							\
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate  * If a signal is taken, we return from the system call wrapper with
4417c478bd9Sstevel@tonic-gate  * our original signal mask restored (see code in call_user_handler()).
4427c478bd9Sstevel@tonic-gate  * If not (self->ul_sigsuspend is still non-zero), we must restore our
4437c478bd9Sstevel@tonic-gate  * original signal mask ourself.
4447c478bd9Sstevel@tonic-gate  */
4457c478bd9Sstevel@tonic-gate #define	EPILOGUE_MASK							\
4467c478bd9Sstevel@tonic-gate 	if (nocancel == 0) {						\
4477c478bd9Sstevel@tonic-gate 		self->ul_sp = 0;					\
4487c478bd9Sstevel@tonic-gate 		self->ul_cancel_async = self->ul_save_async;		\
4497c478bd9Sstevel@tonic-gate 	}								\
4507c478bd9Sstevel@tonic-gate 	if (self->ul_sigsuspend) {					\
4517c478bd9Sstevel@tonic-gate 		self->ul_sigsuspend = 0;				\
4527c478bd9Sstevel@tonic-gate 		restore_signals(self);					\
4537c478bd9Sstevel@tonic-gate 	}								\
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate 
45634709573Sraf /*
457f841f6adSraf  * Cancellation prologue and epilogue functions,
458f841f6adSraf  * for cancellation points too complex to include here.
45934709573Sraf  */
46034709573Sraf void
46134709573Sraf _cancel_prologue(void)
46234709573Sraf {
46334709573Sraf 	ulwp_t *self = curthread;
46434709573Sraf 
465a574db85Sraf 	self->ul_cancel_prologue =
466a574db85Sraf 	    (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks |
467a574db85Sraf 	    self->ul_critical | self->ul_sigdefer) != 0;
46834709573Sraf 	if (self->ul_cancel_prologue == 0) {
46934709573Sraf 		self->ul_save_async = self->ul_cancel_async;
47034709573Sraf 		if (!self->ul_cancel_disabled) {
47134709573Sraf 			self->ul_cancel_async = 1;
47234709573Sraf 			if (self->ul_cancel_pending)
4737257d1b4Sraf 				pthread_exit(PTHREAD_CANCELED);
47434709573Sraf 		}
47534709573Sraf 		self->ul_sp = stkptr();
476a574db85Sraf 	} else if (self->ul_cancel_pending &&
477a574db85Sraf 	    !self->ul_cancel_disabled) {
478a574db85Sraf 		set_cancel_eintr_flag(self);
47934709573Sraf 	}
48034709573Sraf }
48134709573Sraf 
48234709573Sraf void
48334709573Sraf _cancel_epilogue(void)
48434709573Sraf {
48534709573Sraf 	ulwp_t *self = curthread;
48634709573Sraf 
48734709573Sraf 	if (self->ul_cancel_prologue == 0) {
48834709573Sraf 		self->ul_sp = 0;
48934709573Sraf 		self->ul_cancel_async = self->ul_save_async;
49034709573Sraf 	}
49134709573Sraf }
49234709573Sraf 
4937c478bd9Sstevel@tonic-gate /*
4947c478bd9Sstevel@tonic-gate  * Called from _thrp_join() (thr_join() is a cancellation point)
4957c478bd9Sstevel@tonic-gate  */
4967c478bd9Sstevel@tonic-gate int
4977c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found)
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate 	int error;
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	PROLOGUE
502a574db85Sraf 	if (abort)
503a574db85Sraf 		return (EINTR);
504a574db85Sraf 	while ((error = __lwp_wait(tid, found)) == EINTR && !cancel_active())
505a574db85Sraf 		continue;
5067c478bd9Sstevel@tonic-gate 	EPILOGUE
5077c478bd9Sstevel@tonic-gate 	return (error);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate ssize_t
5117257d1b4Sraf read(int fd, void *buf, size_t size)
5127c478bd9Sstevel@tonic-gate {
513a574db85Sraf 	extern ssize_t __read(int, void *, size_t);
5147c478bd9Sstevel@tonic-gate 	ssize_t rv;
5157c478bd9Sstevel@tonic-gate 
516a574db85Sraf 	PERFORM(__read(fd, buf, size))
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate ssize_t
5207257d1b4Sraf write(int fd, const void *buf, size_t size)
5217c478bd9Sstevel@tonic-gate {
522a574db85Sraf 	extern ssize_t __write(int, const void *, size_t);
5237c478bd9Sstevel@tonic-gate 	ssize_t rv;
5247c478bd9Sstevel@tonic-gate 
525a574db85Sraf 	PERFORM(__write(fd, buf, size))
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate int
5297257d1b4Sraf getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr,
5307c478bd9Sstevel@tonic-gate 	int *flagsp)
5317c478bd9Sstevel@tonic-gate {
532a574db85Sraf 	extern int __getmsg(int, struct strbuf *, struct strbuf *, int *);
5337c478bd9Sstevel@tonic-gate 	int rv;
5347c478bd9Sstevel@tonic-gate 
535a574db85Sraf 	PERFORM(__getmsg(fd, ctlptr, dataptr, flagsp))
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate int
5397257d1b4Sraf getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr,
5407c478bd9Sstevel@tonic-gate 	int *bandp, int *flagsp)
5417c478bd9Sstevel@tonic-gate {
542a574db85Sraf 	extern int __getpmsg(int, struct strbuf *, struct strbuf *,
5432e145884Sraf 	    int *, int *);
5447c478bd9Sstevel@tonic-gate 	int rv;
5457c478bd9Sstevel@tonic-gate 
546a574db85Sraf 	PERFORM(__getpmsg(fd, ctlptr, dataptr, bandp, flagsp))
5477c478bd9Sstevel@tonic-gate }
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate int
5507257d1b4Sraf putmsg(int fd, const struct strbuf *ctlptr,
5517c478bd9Sstevel@tonic-gate 	const struct strbuf *dataptr, int flags)
5527c478bd9Sstevel@tonic-gate {
553a574db85Sraf 	extern int __putmsg(int, const struct strbuf *,
5542e145884Sraf 	    const struct strbuf *, int);
5557c478bd9Sstevel@tonic-gate 	int rv;
5567c478bd9Sstevel@tonic-gate 
557a574db85Sraf 	PERFORM(__putmsg(fd, ctlptr, dataptr, flags))
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate int
5617c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr,
5627c478bd9Sstevel@tonic-gate 	const struct strbuf *dataptr, int flags)
5637c478bd9Sstevel@tonic-gate {
564a574db85Sraf 	extern int __putmsg(int, const struct strbuf *,
5652e145884Sraf 	    const struct strbuf *, int);
5667c478bd9Sstevel@tonic-gate 	int rv;
5677c478bd9Sstevel@tonic-gate 
568a574db85Sraf 	PERFORM(__putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4))
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate int
5727257d1b4Sraf putpmsg(int fd, const struct strbuf *ctlptr,
5737c478bd9Sstevel@tonic-gate 	const struct strbuf *dataptr, int band, int flags)
5747c478bd9Sstevel@tonic-gate {
575a574db85Sraf 	extern int __putpmsg(int, const struct strbuf *,
5762e145884Sraf 	    const struct strbuf *, int, int);
5777c478bd9Sstevel@tonic-gate 	int rv;
5787c478bd9Sstevel@tonic-gate 
579a574db85Sraf 	PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags))
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate int
5837c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr,
5847c478bd9Sstevel@tonic-gate 	const struct strbuf *dataptr, int band, int flags)
5857c478bd9Sstevel@tonic-gate {
586a574db85Sraf 	extern int __putpmsg(int, const struct strbuf *,
5872e145884Sraf 	    const struct strbuf *, int, int);
5887c478bd9Sstevel@tonic-gate 	int rv;
5897c478bd9Sstevel@tonic-gate 
590a574db85Sraf 	PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4))
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate int
5947257d1b4Sraf nanosleep(const timespec_t *rqtp, timespec_t *rmtp)
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate 	int error;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	PROLOGUE
599a574db85Sraf 	error = abort? EINTR : __nanosleep(rqtp, rmtp);
6007c478bd9Sstevel@tonic-gate 	EPILOGUE
6017c478bd9Sstevel@tonic-gate 	if (error) {
6027c478bd9Sstevel@tonic-gate 		errno = error;
6037c478bd9Sstevel@tonic-gate 		return (-1);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 	return (0);
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate int
6097257d1b4Sraf clock_nanosleep(clockid_t clock_id, int flags,
6107c478bd9Sstevel@tonic-gate 	const timespec_t *rqtp, timespec_t *rmtp)
6117c478bd9Sstevel@tonic-gate {
6127c478bd9Sstevel@tonic-gate 	timespec_t reltime;
6137c478bd9Sstevel@tonic-gate 	hrtime_t start;
6147c478bd9Sstevel@tonic-gate 	hrtime_t rqlapse;
6157c478bd9Sstevel@tonic-gate 	hrtime_t lapse;
6167c478bd9Sstevel@tonic-gate 	int error;
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	switch (clock_id) {
6197c478bd9Sstevel@tonic-gate 	case CLOCK_VIRTUAL:
6207c478bd9Sstevel@tonic-gate 	case CLOCK_PROCESS_CPUTIME_ID:
6217c478bd9Sstevel@tonic-gate 	case CLOCK_THREAD_CPUTIME_ID:
6227c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
6237c478bd9Sstevel@tonic-gate 	case CLOCK_REALTIME:
6247c478bd9Sstevel@tonic-gate 	case CLOCK_HIGHRES:
6257c478bd9Sstevel@tonic-gate 		break;
6267c478bd9Sstevel@tonic-gate 	default:
6277c478bd9Sstevel@tonic-gate 		return (EINVAL);
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 	if (flags & TIMER_ABSTIME) {
6307c478bd9Sstevel@tonic-gate 		abstime_to_reltime(clock_id, rqtp, &reltime);
6317c478bd9Sstevel@tonic-gate 		rmtp = NULL;
6327c478bd9Sstevel@tonic-gate 	} else {
6337c478bd9Sstevel@tonic-gate 		reltime = *rqtp;
6347c478bd9Sstevel@tonic-gate 		if (clock_id == CLOCK_HIGHRES)
6357c478bd9Sstevel@tonic-gate 			start = gethrtime();
6367c478bd9Sstevel@tonic-gate 	}
6377c478bd9Sstevel@tonic-gate restart:
6387c478bd9Sstevel@tonic-gate 	PROLOGUE
639a574db85Sraf 	error = abort? EINTR : __nanosleep(&reltime, rmtp);
6407c478bd9Sstevel@tonic-gate 	EPILOGUE
6417c478bd9Sstevel@tonic-gate 	if (error == 0 && clock_id == CLOCK_HIGHRES) {
6427c478bd9Sstevel@tonic-gate 		/*
6437c478bd9Sstevel@tonic-gate 		 * Don't return yet if we didn't really get a timeout.
6447c478bd9Sstevel@tonic-gate 		 * This can happen if we return because someone resets
6457c478bd9Sstevel@tonic-gate 		 * the system clock.
6467c478bd9Sstevel@tonic-gate 		 */
6477c478bd9Sstevel@tonic-gate 		if (flags & TIMER_ABSTIME) {
6487c478bd9Sstevel@tonic-gate 			if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC +
6497c478bd9Sstevel@tonic-gate 			    rqtp->tv_nsec > gethrtime()) {
6507c478bd9Sstevel@tonic-gate 				abstime_to_reltime(clock_id, rqtp, &reltime);
6517c478bd9Sstevel@tonic-gate 				goto restart;
6527c478bd9Sstevel@tonic-gate 			}
6537c478bd9Sstevel@tonic-gate 		} else {
6547c478bd9Sstevel@tonic-gate 			rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC +
6552e145884Sraf 			    rqtp->tv_nsec;
6567c478bd9Sstevel@tonic-gate 			lapse = gethrtime() - start;
6577c478bd9Sstevel@tonic-gate 			if (rqlapse > lapse) {
6587c478bd9Sstevel@tonic-gate 				hrt2ts(rqlapse - lapse, &reltime);
6597c478bd9Sstevel@tonic-gate 				goto restart;
6607c478bd9Sstevel@tonic-gate 			}
6617c478bd9Sstevel@tonic-gate 		}
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 	if (error == 0 && clock_id == CLOCK_REALTIME &&
6647c478bd9Sstevel@tonic-gate 	    (flags & TIMER_ABSTIME)) {
6657c478bd9Sstevel@tonic-gate 		/*
6667c478bd9Sstevel@tonic-gate 		 * Don't return yet just because someone reset the
6677c478bd9Sstevel@tonic-gate 		 * system clock.  Recompute the new relative time
6687c478bd9Sstevel@tonic-gate 		 * and reissue the nanosleep() call if necessary.
6697c478bd9Sstevel@tonic-gate 		 *
6707c478bd9Sstevel@tonic-gate 		 * Resetting the system clock causes all sorts of
6717c478bd9Sstevel@tonic-gate 		 * problems and the SUSV3 standards body should
6727c478bd9Sstevel@tonic-gate 		 * have made the behavior of clock_nanosleep() be
6737c478bd9Sstevel@tonic-gate 		 * implementation-defined in such a case rather than
6747c478bd9Sstevel@tonic-gate 		 * being specific about honoring the new system time.
6757c478bd9Sstevel@tonic-gate 		 * Standards bodies are filled with fools and idiots.
6767c478bd9Sstevel@tonic-gate 		 */
6777c478bd9Sstevel@tonic-gate 		abstime_to_reltime(clock_id, rqtp, &reltime);
6787c478bd9Sstevel@tonic-gate 		if (reltime.tv_sec != 0 || reltime.tv_nsec != 0)
6797c478bd9Sstevel@tonic-gate 			goto restart;
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 	return (error);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate unsigned int
6857257d1b4Sraf sleep(unsigned int sec)
6867c478bd9Sstevel@tonic-gate {
6877c478bd9Sstevel@tonic-gate 	unsigned int rem = 0;
6887c478bd9Sstevel@tonic-gate 	timespec_t ts;
6897c478bd9Sstevel@tonic-gate 	timespec_t tsr;
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	ts.tv_sec = (time_t)sec;
6927c478bd9Sstevel@tonic-gate 	ts.tv_nsec = 0;
6937257d1b4Sraf 	if (nanosleep(&ts, &tsr) == -1 && errno == EINTR) {
6947c478bd9Sstevel@tonic-gate 		rem = (unsigned int)tsr.tv_sec;
6957c478bd9Sstevel@tonic-gate 		if (tsr.tv_nsec >= NANOSEC / 2)
6967c478bd9Sstevel@tonic-gate 			rem++;
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 	return (rem);
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate int
7027257d1b4Sraf usleep(useconds_t usec)
7037c478bd9Sstevel@tonic-gate {
7047c478bd9Sstevel@tonic-gate 	timespec_t ts;
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	ts.tv_sec = usec / MICROSEC;
7077c478bd9Sstevel@tonic-gate 	ts.tv_nsec = (long)(usec % MICROSEC) * 1000;
7087257d1b4Sraf 	(void) nanosleep(&ts, NULL);
7097c478bd9Sstevel@tonic-gate 	return (0);
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate int
7137257d1b4Sraf close(int fildes)
7147c478bd9Sstevel@tonic-gate {
715f841f6adSraf 	extern void _aio_close(int);
716a574db85Sraf 	extern int __close(int);
7177c478bd9Sstevel@tonic-gate 	int rv;
7187c478bd9Sstevel@tonic-gate 
719720d4a35Sraf 	/*
720720d4a35Sraf 	 * If we call _aio_close() while in a critical region,
721720d4a35Sraf 	 * we will draw an ASSERT() failure, so don't do it.
722720d4a35Sraf 	 * No calls to close() from within libc need _aio_close();
723720d4a35Sraf 	 * only the application's calls to close() need this,
724720d4a35Sraf 	 * and such calls are never from a libc critical region.
725720d4a35Sraf 	 */
726720d4a35Sraf 	if (curthread->ul_critical == 0)
727720d4a35Sraf 		_aio_close(fildes);
728a574db85Sraf 	PERFORM(__close(fildes))
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate 
731a574db85Sraf int
7327257d1b4Sraf door_call(int d, door_arg_t *params)
733a574db85Sraf {
734a574db85Sraf 	extern int __door_call(int, door_arg_t *);
735a574db85Sraf 	int rv;
736a574db85Sraf 
737a574db85Sraf 	PERFORM(__door_call(d, params))
738a574db85Sraf }
739a574db85Sraf 
7407c478bd9Sstevel@tonic-gate int
7417257d1b4Sraf fcntl(int fildes, int cmd, ...)
7427c478bd9Sstevel@tonic-gate {
743a574db85Sraf 	extern int __fcntl(int, int, ...);
7447c478bd9Sstevel@tonic-gate 	intptr_t arg;
7457c478bd9Sstevel@tonic-gate 	int rv;
7467c478bd9Sstevel@tonic-gate 	va_list ap;
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	va_start(ap, cmd);
7497c478bd9Sstevel@tonic-gate 	arg = va_arg(ap, intptr_t);
7507c478bd9Sstevel@tonic-gate 	va_end(ap);
7517c478bd9Sstevel@tonic-gate 	if (cmd != F_SETLKW)
752a574db85Sraf 		return (__fcntl(fildes, cmd, arg));
753a574db85Sraf 	PERFORM(__fcntl(fildes, cmd, arg))
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate 
7561f8cf95fSraf int
7577257d1b4Sraf fdatasync(int fildes)
7581f8cf95fSraf {
759a574db85Sraf 	extern int __fdsync(int, int);
7601f8cf95fSraf 	int rv;
7611f8cf95fSraf 
762a574db85Sraf 	PERFORM(__fdsync(fildes, FDSYNC))
7631f8cf95fSraf }
7641f8cf95fSraf 
7657c478bd9Sstevel@tonic-gate int
7667257d1b4Sraf fsync(int fildes)
7677c478bd9Sstevel@tonic-gate {
768a574db85Sraf 	extern int __fdsync(int, int);
7697c478bd9Sstevel@tonic-gate 	int rv;
7707c478bd9Sstevel@tonic-gate 
771a574db85Sraf 	PERFORM(__fdsync(fildes, FSYNC))
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate int
7757257d1b4Sraf lockf(int fildes, int function, off_t size)
7767c478bd9Sstevel@tonic-gate {
777a574db85Sraf 	extern int __lockf(int, int, off_t);
7787c478bd9Sstevel@tonic-gate 	int rv;
7797c478bd9Sstevel@tonic-gate 
780a574db85Sraf 	PERFORM(__lockf(fildes, function, size))
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate #if !defined(_LP64)
7847c478bd9Sstevel@tonic-gate int
7857257d1b4Sraf lockf64(int fildes, int function, off64_t size)
7867c478bd9Sstevel@tonic-gate {
787a574db85Sraf 	extern int __lockf64(int, int, off64_t);
7887c478bd9Sstevel@tonic-gate 	int rv;
7897c478bd9Sstevel@tonic-gate 
790a574db85Sraf 	PERFORM(__lockf64(fildes, function, size))
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate #endif	/* !_LP64 */
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate ssize_t
7957257d1b4Sraf msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
7967c478bd9Sstevel@tonic-gate {
797a574db85Sraf 	extern ssize_t __msgrcv(int, void *, size_t, long, int);
7987c478bd9Sstevel@tonic-gate 	ssize_t rv;
7997c478bd9Sstevel@tonic-gate 
800a574db85Sraf 	PERFORM(__msgrcv(msqid, msgp, msgsz, msgtyp, msgflg))
801a574db85Sraf }
802a574db85Sraf 
803a574db85Sraf int
8047257d1b4Sraf msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
805a574db85Sraf {
806a574db85Sraf 	extern int __msgsnd(int, const void *, size_t, int);
807a574db85Sraf 	int rv;
808a574db85Sraf 
809a574db85Sraf 	PERFORM(__msgsnd(msqid, msgp, msgsz, msgflg))
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate int
8137257d1b4Sraf msync(caddr_t addr, size_t len, int flags)
8147c478bd9Sstevel@tonic-gate {
815a574db85Sraf 	extern int __msync(caddr_t, size_t, int);
8167c478bd9Sstevel@tonic-gate 	int rv;
8177c478bd9Sstevel@tonic-gate 
818a574db85Sraf 	PERFORM(__msync(addr, len, flags))
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate int
8228fd04b83SRoger A. Faulkner openat(int fd, const char *path, int oflag, ...)
8237c478bd9Sstevel@tonic-gate {
824a574db85Sraf 	mode_t mode;
8257c478bd9Sstevel@tonic-gate 	int rv;
826a574db85Sraf 	va_list ap;
8277c478bd9Sstevel@tonic-gate 
828a574db85Sraf 	va_start(ap, oflag);
829a574db85Sraf 	mode = va_arg(ap, mode_t);
830a574db85Sraf 	va_end(ap);
8318fd04b83SRoger A. Faulkner 	PERFORM(__openat(fd, path, oflag, mode))
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate int
8358fd04b83SRoger A. Faulkner open(const char *path, int oflag, ...)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate 	mode_t mode;
8387c478bd9Sstevel@tonic-gate 	int rv;
8397c478bd9Sstevel@tonic-gate 	va_list ap;
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	va_start(ap, oflag);
8427c478bd9Sstevel@tonic-gate 	mode = va_arg(ap, mode_t);
8437c478bd9Sstevel@tonic-gate 	va_end(ap);
8448fd04b83SRoger A. Faulkner 	PERFORM(__open(path, oflag, mode))
8458fd04b83SRoger A. Faulkner }
8468fd04b83SRoger A. Faulkner 
8478fd04b83SRoger A. Faulkner int
8488fd04b83SRoger A. Faulkner creat(const char *path, mode_t mode)
8498fd04b83SRoger A. Faulkner {
8508fd04b83SRoger A. Faulkner 	return (open(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
8517c478bd9Sstevel@tonic-gate }
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate #if !defined(_LP64)
854a574db85Sraf int
8558fd04b83SRoger A. Faulkner openat64(int fd, const char *path, int oflag, ...)
856a574db85Sraf {
857a574db85Sraf 	mode_t mode;
858a574db85Sraf 	int rv;
859a574db85Sraf 	va_list ap;
860a574db85Sraf 
861a574db85Sraf 	va_start(ap, oflag);
862a574db85Sraf 	mode = va_arg(ap, mode_t);
863a574db85Sraf 	va_end(ap);
8648fd04b83SRoger A. Faulkner 	PERFORM(__openat64(fd, path, oflag, mode))
865a574db85Sraf }
866a574db85Sraf 
8677c478bd9Sstevel@tonic-gate int
8688fd04b83SRoger A. Faulkner open64(const char *path, int oflag, ...)
8697c478bd9Sstevel@tonic-gate {
8707c478bd9Sstevel@tonic-gate 	mode_t mode;
8717c478bd9Sstevel@tonic-gate 	int rv;
8727c478bd9Sstevel@tonic-gate 	va_list ap;
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	va_start(ap, oflag);
8757c478bd9Sstevel@tonic-gate 	mode = va_arg(ap, mode_t);
8767c478bd9Sstevel@tonic-gate 	va_end(ap);
8778fd04b83SRoger A. Faulkner 	PERFORM(__open64(path, oflag, mode))
8788fd04b83SRoger A. Faulkner }
8798fd04b83SRoger A. Faulkner 
8808fd04b83SRoger A. Faulkner int
8818fd04b83SRoger A. Faulkner creat64(const char *path, mode_t mode)
8828fd04b83SRoger A. Faulkner {
8838fd04b83SRoger A. Faulkner 	return (open64(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
8847c478bd9Sstevel@tonic-gate }
8857c478bd9Sstevel@tonic-gate #endif	/* !_LP64 */
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate int
8887257d1b4Sraf pause(void)
8897c478bd9Sstevel@tonic-gate {
890a574db85Sraf 	extern int __pause(void);
8917c478bd9Sstevel@tonic-gate 	int rv;
8927c478bd9Sstevel@tonic-gate 
893a574db85Sraf 	PERFORM(__pause())
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate ssize_t
8977257d1b4Sraf pread(int fildes, void *buf, size_t nbyte, off_t offset)
8987c478bd9Sstevel@tonic-gate {
899a574db85Sraf 	extern ssize_t __pread(int, void *, size_t, off_t);
9007c478bd9Sstevel@tonic-gate 	ssize_t rv;
9017c478bd9Sstevel@tonic-gate 
902a574db85Sraf 	PERFORM(__pread(fildes, buf, nbyte, offset))
9037c478bd9Sstevel@tonic-gate }
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate #if !defined(_LP64)
9067c478bd9Sstevel@tonic-gate ssize_t
9077257d1b4Sraf pread64(int fildes, void *buf, size_t nbyte, off64_t offset)
9087c478bd9Sstevel@tonic-gate {
909a574db85Sraf 	extern ssize_t __pread64(int, void *, size_t, off64_t);
9107c478bd9Sstevel@tonic-gate 	ssize_t rv;
9117c478bd9Sstevel@tonic-gate 
912a574db85Sraf 	PERFORM(__pread64(fildes, buf, nbyte, offset))
9137c478bd9Sstevel@tonic-gate }
914*fca543caSDJ Hoffman 
915*fca543caSDJ Hoffman ssize_t
916*fca543caSDJ Hoffman preadv64(int fildes, const struct iovec *iov, int iovcnt, off64_t offset)
917*fca543caSDJ Hoffman {
918*fca543caSDJ Hoffman 
919*fca543caSDJ Hoffman 	extern ssize_t __preadv64(int, const struct iovec *, int, off_t, off_t);
920*fca543caSDJ Hoffman 	ssize_t rv;
921*fca543caSDJ Hoffman 
922*fca543caSDJ Hoffman 	PERFORM(__preadv64(fildes, iov, iovcnt, offset & 0xffffffffULL,
923*fca543caSDJ Hoffman 	    offset>>32))
924*fca543caSDJ Hoffman }
9257c478bd9Sstevel@tonic-gate #endif	/* !_LP64 */
9267c478bd9Sstevel@tonic-gate 
927*fca543caSDJ Hoffman ssize_t
928*fca543caSDJ Hoffman preadv(int fildes, const struct iovec *iov, int iovcnt, off_t offset)
929*fca543caSDJ Hoffman {
930*fca543caSDJ Hoffman 
931*fca543caSDJ Hoffman 	extern ssize_t __preadv(int, const struct iovec *, int, off_t, off_t);
932*fca543caSDJ Hoffman 	ssize_t rv;
933*fca543caSDJ Hoffman 
934*fca543caSDJ Hoffman 	PERFORM(__preadv(fildes, iov, iovcnt, offset, 0))
935*fca543caSDJ Hoffman }
9367c478bd9Sstevel@tonic-gate ssize_t
9377257d1b4Sraf pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
9387c478bd9Sstevel@tonic-gate {
939a574db85Sraf 	extern ssize_t __pwrite(int, const void *, size_t, off_t);
9407c478bd9Sstevel@tonic-gate 	ssize_t rv;
9417c478bd9Sstevel@tonic-gate 
942a574db85Sraf 	PERFORM(__pwrite(fildes, buf, nbyte, offset))
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate #if !defined(_LP64)
9467c478bd9Sstevel@tonic-gate ssize_t
9477257d1b4Sraf pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset)
9487c478bd9Sstevel@tonic-gate {
949a574db85Sraf 	extern ssize_t __pwrite64(int, const void *, size_t, off64_t);
9507c478bd9Sstevel@tonic-gate 	ssize_t rv;
9517c478bd9Sstevel@tonic-gate 
952a574db85Sraf 	PERFORM(__pwrite64(fildes, buf, nbyte, offset))
9537c478bd9Sstevel@tonic-gate }
954*fca543caSDJ Hoffman 
955*fca543caSDJ Hoffman ssize_t
956*fca543caSDJ Hoffman pwritev64(int fildes, const struct iovec *iov, int iovcnt, off64_t offset)
957*fca543caSDJ Hoffman {
958*fca543caSDJ Hoffman 
959*fca543caSDJ Hoffman 	extern ssize_t __pwritev64(int,
960*fca543caSDJ Hoffman 	    const struct iovec *, int, off_t, off_t);
961*fca543caSDJ Hoffman 	ssize_t rv;
962*fca543caSDJ Hoffman 
963*fca543caSDJ Hoffman 	PERFORM(__pwritev64(fildes, iov, iovcnt, offset &
964*fca543caSDJ Hoffman 	    0xffffffffULL, offset>>32))
965*fca543caSDJ Hoffman }
966*fca543caSDJ Hoffman 
9677c478bd9Sstevel@tonic-gate #endif	/* !_LP64 */
9687c478bd9Sstevel@tonic-gate 
969*fca543caSDJ Hoffman ssize_t
970*fca543caSDJ Hoffman pwritev(int fildes, const struct iovec *iov, int iovcnt, off_t offset)
971*fca543caSDJ Hoffman {
972*fca543caSDJ Hoffman 	extern ssize_t __pwritev(int, const struct iovec *, int, off_t, off_t);
973*fca543caSDJ Hoffman 	ssize_t rv;
974*fca543caSDJ Hoffman 
975*fca543caSDJ Hoffman 	PERFORM(__pwritev(fildes, iov, iovcnt, offset, 0))
976*fca543caSDJ Hoffman }
977*fca543caSDJ Hoffman 
9787c478bd9Sstevel@tonic-gate ssize_t
9797257d1b4Sraf readv(int fildes, const struct iovec *iov, int iovcnt)
9807c478bd9Sstevel@tonic-gate {
981a574db85Sraf 	extern ssize_t __readv(int, const struct iovec *, int);
9827c478bd9Sstevel@tonic-gate 	ssize_t rv;
9837c478bd9Sstevel@tonic-gate 
984a574db85Sraf 	PERFORM(__readv(fildes, iov, iovcnt))
9857c478bd9Sstevel@tonic-gate }
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate int
9887257d1b4Sraf sigpause(int sig)
9897c478bd9Sstevel@tonic-gate {
990a574db85Sraf 	extern int __sigpause(int);
9917c478bd9Sstevel@tonic-gate 	int rv;
9927c478bd9Sstevel@tonic-gate 
993a574db85Sraf 	PERFORM(__sigpause(sig))
9947c478bd9Sstevel@tonic-gate }
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate int
9977257d1b4Sraf sigsuspend(const sigset_t *set)
9987c478bd9Sstevel@tonic-gate {
9997c478bd9Sstevel@tonic-gate 	extern int __sigsuspend(const sigset_t *);
10007c478bd9Sstevel@tonic-gate 	int rv;
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	PROLOGUE_MASK(set)
10037c478bd9Sstevel@tonic-gate 	rv = __sigsuspend(set);
10047c478bd9Sstevel@tonic-gate 	EPILOGUE_MASK
10057c478bd9Sstevel@tonic-gate 	return (rv);
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate int
10097c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout,
10107c478bd9Sstevel@tonic-gate 	const sigset_t *sigmask)
10117c478bd9Sstevel@tonic-gate {
10127c478bd9Sstevel@tonic-gate 	extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *,
10132e145884Sraf 	    const sigset_t *);
10147c478bd9Sstevel@tonic-gate 	int rv;
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	PROLOGUE_MASK(sigmask)
10177c478bd9Sstevel@tonic-gate 	rv = __pollsys(fds, nfd, timeout, sigmask);
10187c478bd9Sstevel@tonic-gate 	EPILOGUE_MASK
10197c478bd9Sstevel@tonic-gate 	return (rv);
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate int
10237257d1b4Sraf sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout)
10247c478bd9Sstevel@tonic-gate {
1025f841f6adSraf 	extern int __sigtimedwait(const sigset_t *, siginfo_t *,
10262e145884Sraf 	    const timespec_t *);
10277c478bd9Sstevel@tonic-gate 	siginfo_t info;
10287c478bd9Sstevel@tonic-gate 	int sig;
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 	PROLOGUE
1031a574db85Sraf 	if (abort) {
1032a574db85Sraf 		*self->ul_errnop = EINTR;
10337c478bd9Sstevel@tonic-gate 		sig = -1;
1034a574db85Sraf 	} else {
1035a574db85Sraf 		sig = __sigtimedwait(set, &info, timeout);
1036a574db85Sraf 		if (sig == SIGCANCEL &&
1037a574db85Sraf 		    (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) {
1038a574db85Sraf 			do_sigcancel();
1039a574db85Sraf 			*self->ul_errnop = EINTR;
1040a574db85Sraf 			sig = -1;
1041a574db85Sraf 		}
10427c478bd9Sstevel@tonic-gate 	}
10437c478bd9Sstevel@tonic-gate 	EPILOGUE
10447c478bd9Sstevel@tonic-gate 	if (sig != -1 && infop)
10458cd45542Sraf 		(void) memcpy(infop, &info, sizeof (*infop));
10467c478bd9Sstevel@tonic-gate 	return (sig);
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate int
10507257d1b4Sraf sigwait(sigset_t *set)
10517c478bd9Sstevel@tonic-gate {
10527257d1b4Sraf 	return (sigtimedwait(set, NULL, NULL));
1053f841f6adSraf }
1054f841f6adSraf 
1055f841f6adSraf int
10567257d1b4Sraf sigwaitinfo(const sigset_t *set, siginfo_t *info)
1057f841f6adSraf {
10587257d1b4Sraf 	return (sigtimedwait(set, info, NULL));
1059f841f6adSraf }
1060f841f6adSraf 
1061f841f6adSraf int
10627257d1b4Sraf sigqueue(pid_t pid, int signo, const union sigval value)
1063f841f6adSraf {
1064f841f6adSraf 	extern int __sigqueue(pid_t pid, int signo,
10652e145884Sraf 	    /* const union sigval */ void *value, int si_code, int block);
1066f841f6adSraf 	return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0));
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate int
10705dbfd19aSTheo Schlossnagle _so_accept(int sock, struct sockaddr *addr, uint_t *addrlen, int version,
10715dbfd19aSTheo Schlossnagle     int flags)
10727c478bd9Sstevel@tonic-gate {
10735dbfd19aSTheo Schlossnagle 	extern int __so_accept(int, struct sockaddr *, uint_t *, int, int);
10747c478bd9Sstevel@tonic-gate 	int rv;
10757c478bd9Sstevel@tonic-gate 
10765dbfd19aSTheo Schlossnagle 	PERFORM(__so_accept(sock, addr, addrlen, version, flags))
10777c478bd9Sstevel@tonic-gate }
10787c478bd9Sstevel@tonic-gate 
1079a574db85Sraf int
1080a574db85Sraf _so_connect(int sock, struct sockaddr *addr, uint_t addrlen, int version)
10817c478bd9Sstevel@tonic-gate {
1082a574db85Sraf 	extern int __so_connect(int, struct sockaddr *, uint_t, int);
1083a574db85Sraf 	int rv;
10847c478bd9Sstevel@tonic-gate 
1085a574db85Sraf 	PERFORM(__so_connect(sock, addr, addrlen, version))
10867c478bd9Sstevel@tonic-gate }
10877c478bd9Sstevel@tonic-gate 
1088a574db85Sraf int
1089a574db85Sraf _so_recv(int sock, void *buf, size_t len, int flags)
10907c478bd9Sstevel@tonic-gate {
1091a574db85Sraf 	extern int __so_recv(int, void *, size_t, int);
1092a574db85Sraf 	int rv;
10937c478bd9Sstevel@tonic-gate 
1094a574db85Sraf 	PERFORM(__so_recv(sock, buf, len, flags))
10957c478bd9Sstevel@tonic-gate }
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate int
1098a574db85Sraf _so_recvfrom(int sock, void *buf, size_t len, int flags,
1099a574db85Sraf     struct sockaddr *addr, int *addrlen)
11007c478bd9Sstevel@tonic-gate {
1101a574db85Sraf 	extern int __so_recvfrom(int, void *, size_t, int,
1102a574db85Sraf 	    struct sockaddr *, int *);
11037c478bd9Sstevel@tonic-gate 	int rv;
11047c478bd9Sstevel@tonic-gate 
1105a574db85Sraf 	PERFORM(__so_recvfrom(sock, buf, len, flags, addr, addrlen))
11067c478bd9Sstevel@tonic-gate }
11077c478bd9Sstevel@tonic-gate 
1108a574db85Sraf int
1109a574db85Sraf _so_recvmsg(int sock, struct msghdr *msg, int flags)
1110a574db85Sraf {
1111a574db85Sraf 	extern int __so_recvmsg(int, struct msghdr *, int);
1112a574db85Sraf 	int rv;
1113a574db85Sraf 
1114a574db85Sraf 	PERFORM(__so_recvmsg(sock, msg, flags))
1115a574db85Sraf }
1116a574db85Sraf 
1117a574db85Sraf int
1118a574db85Sraf _so_send(int sock, const void *buf, size_t len, int flags)
1119a574db85Sraf {
1120a574db85Sraf 	extern int __so_send(int, const void *, size_t, int);
1121a574db85Sraf 	int rv;
1122a574db85Sraf 
1123a574db85Sraf 	PERFORM(__so_send(sock, buf, len, flags))
1124a574db85Sraf }
1125a574db85Sraf 
1126a574db85Sraf int
1127a574db85Sraf _so_sendmsg(int sock, const struct msghdr *msg, int flags)
11287c478bd9Sstevel@tonic-gate {
1129a574db85Sraf 	extern int __so_sendmsg(int, const struct msghdr *, int);
1130a574db85Sraf 	int rv;
1131a574db85Sraf 
1132a574db85Sraf 	PERFORM(__so_sendmsg(sock, msg, flags))
1133a574db85Sraf }
1134a574db85Sraf 
1135a574db85Sraf int
1136a574db85Sraf _so_sendto(int sock, const void *buf, size_t len, int flags,
1137a574db85Sraf     const struct sockaddr *addr, int *addrlen)
1138a574db85Sraf {
1139a574db85Sraf 	extern int __so_sendto(int, const void *, size_t, int,
1140a574db85Sraf 	    const struct sockaddr *, int *);
1141a574db85Sraf 	int rv;
1142a574db85Sraf 
1143a574db85Sraf 	PERFORM(__so_sendto(sock, buf, len, flags, addr, addrlen))
1144a574db85Sraf }
1145a574db85Sraf 
1146a574db85Sraf int
11477257d1b4Sraf tcdrain(int fildes)
1148a574db85Sraf {
1149a574db85Sraf 	extern int __tcdrain(int);
1150a574db85Sraf 	int rv;
1151a574db85Sraf 
1152a574db85Sraf 	PERFORM(__tcdrain(fildes))
1153a574db85Sraf }
1154a574db85Sraf 
1155a574db85Sraf int
11567257d1b4Sraf waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
1157a574db85Sraf {
1158a574db85Sraf 	extern int __waitid(idtype_t, id_t, siginfo_t *, int);
1159a574db85Sraf 	int rv;
11607c478bd9Sstevel@tonic-gate 
1161a574db85Sraf 	if (options & WNOHANG)
1162a574db85Sraf 		return (__waitid(idtype, id, infop, options));
1163a574db85Sraf 	PERFORM(__waitid(idtype, id, infop, options))
11647c478bd9Sstevel@tonic-gate }
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate ssize_t
11677257d1b4Sraf writev(int fildes, const struct iovec *iov, int iovcnt)
11687c478bd9Sstevel@tonic-gate {
1169a574db85Sraf 	extern ssize_t __writev(int, const struct iovec *, int);
11707c478bd9Sstevel@tonic-gate 	ssize_t rv;
11717c478bd9Sstevel@tonic-gate 
1172a574db85Sraf 	PERFORM(__writev(fildes, iov, iovcnt))
11737c478bd9Sstevel@tonic-gate }
1174