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 /* 23a574db85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include "lint.h" 307c478bd9Sstevel@tonic-gate #include "thr_uberdata.h" 317c478bd9Sstevel@tonic-gate #include <stdarg.h> 327c478bd9Sstevel@tonic-gate #include <poll.h> 337c478bd9Sstevel@tonic-gate #include <stropts.h> 347c478bd9Sstevel@tonic-gate #include <dlfcn.h> 35a574db85Sraf #include <wait.h> 36a574db85Sraf #include <sys/socket.h> 377c478bd9Sstevel@tonic-gate #include <sys/uio.h> 38a574db85Sraf #include <sys/file.h> 39a574db85Sraf #include <sys/door.h> 407c478bd9Sstevel@tonic-gate 41*7257d1b4Sraf /* 42*7257d1b4Sraf * These leading-underbar symbols exist because mistakes were made 43*7257d1b4Sraf * in the past that put them into non-SUNWprivate versions of 44*7257d1b4Sraf * the libc mapfiles. They should be eliminated, but oh well... 45*7257d1b4Sraf */ 46*7257d1b4Sraf #pragma weak _fork = fork 47*7257d1b4Sraf #pragma weak _read = read 48*7257d1b4Sraf #pragma weak _write = write 49*7257d1b4Sraf #pragma weak _getmsg = getmsg 50*7257d1b4Sraf #pragma weak _getpmsg = getpmsg 51*7257d1b4Sraf #pragma weak _putmsg = putmsg 52*7257d1b4Sraf #pragma weak _putpmsg = putpmsg 53*7257d1b4Sraf #pragma weak _sleep = sleep 54*7257d1b4Sraf #pragma weak _close = close 55*7257d1b4Sraf #pragma weak _creat = creat 56*7257d1b4Sraf #pragma weak _fcntl = fcntl 57*7257d1b4Sraf #pragma weak _fsync = fsync 58*7257d1b4Sraf #pragma weak _lockf = lockf 59*7257d1b4Sraf #pragma weak _msgrcv = msgrcv 60*7257d1b4Sraf #pragma weak _msgsnd = msgsnd 61*7257d1b4Sraf #pragma weak _msync = msync 62*7257d1b4Sraf #pragma weak _open = open 63*7257d1b4Sraf #pragma weak _openat = openat 64*7257d1b4Sraf #pragma weak _pause = pause 65*7257d1b4Sraf #pragma weak _readv = readv 66*7257d1b4Sraf #pragma weak _sigpause = sigpause 67*7257d1b4Sraf #pragma weak _sigsuspend = sigsuspend 68*7257d1b4Sraf #pragma weak _tcdrain = tcdrain 69*7257d1b4Sraf #pragma weak _waitid = waitid 70*7257d1b4Sraf #pragma weak _writev = writev 71*7257d1b4Sraf 72*7257d1b4Sraf #if !defined(_LP64) 73*7257d1b4Sraf #pragma weak _creat64 = creat64 74*7257d1b4Sraf #pragma weak _lockf64 = lockf64 75*7257d1b4Sraf #pragma weak _open64 = open64 76*7257d1b4Sraf #pragma weak _openat64 = openat64 77*7257d1b4Sraf #pragma weak _pread64 = pread64 78*7257d1b4Sraf #pragma weak _pwrite64 = pwrite64 79*7257d1b4Sraf #endif 80*7257d1b4Sraf 817c478bd9Sstevel@tonic-gate /* 8298c1a6b4Sraf * atfork_lock protects the pthread_atfork() data structures. 8398c1a6b4Sraf * 84b6233ca5Sraf * fork_lock does double-duty. Not only does it (and atfork_lock) 85b6233ca5Sraf * serialize calls to fork() and forkall(), but it also serializes calls 86b6233ca5Sraf * to thr_suspend() and thr_continue() (because fork() and forkall() also 87b6233ca5Sraf * suspend and continue other threads and they want no competition). 88b6233ca5Sraf * 8998c1a6b4Sraf * Functions called in dlopen()ed L10N objects can do anything, including 9098c1a6b4Sraf * call malloc() and free(). Such calls are not fork-safe when protected 9198c1a6b4Sraf * by an ordinary mutex that is acquired in libc's prefork processing 9298c1a6b4Sraf * because, with an interposed malloc library present, there would be a 9398c1a6b4Sraf * lock ordering violation due to the pthread_atfork() prefork function 9498c1a6b4Sraf * in the interposition library acquiring its malloc lock(s) before the 95b6233ca5Sraf * ordinary mutex in libc being acquired by libc's prefork functions. 96b6233ca5Sraf * 9798c1a6b4Sraf * Within libc, calls to malloc() and free() are fork-safe if the calls 9898c1a6b4Sraf * are made while holding no other libc locks. This covers almost all 9998c1a6b4Sraf * of libc's malloc() and free() calls. For those libc code paths, such 10098c1a6b4Sraf * as the above-mentioned L10N calls, that require serialization and that 10198c1a6b4Sraf * may call malloc() or free(), libc uses callout_lock_enter() to perform 10298c1a6b4Sraf * the serialization. This works because callout_lock is not acquired as 10398c1a6b4Sraf * part of running the pthread_atfork() prefork handlers (to avoid the 10498c1a6b4Sraf * lock ordering violation described above). Rather, it is simply 10598c1a6b4Sraf * reinitialized in postfork1_child() to cover the case that some 10698c1a6b4Sraf * now-defunct thread might have been suspended while holding it. 1077c478bd9Sstevel@tonic-gate */ 108b6233ca5Sraf 1092e145884Sraf void 1102e145884Sraf fork_lock_enter(void) 1117c478bd9Sstevel@tonic-gate { 112b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 1138cd45542Sraf (void) mutex_lock(&curthread->ul_uberdata->fork_lock); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate void 1177c478bd9Sstevel@tonic-gate fork_lock_exit(void) 1187c478bd9Sstevel@tonic-gate { 119b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 1208cd45542Sraf (void) mutex_unlock(&curthread->ul_uberdata->fork_lock); 121b6233ca5Sraf } 122b6233ca5Sraf 123a574db85Sraf /* 124a574db85Sraf * Use cancel_safe_mutex_lock() to protect against being cancelled while 125a574db85Sraf * holding callout_lock and calling outside of libc (via L10N plugins). 126a574db85Sraf * We will honor a pending cancellation request when callout_lock_exit() 127a574db85Sraf * is called, by calling cancel_safe_mutex_unlock(). 128a574db85Sraf */ 129b6233ca5Sraf void 13098c1a6b4Sraf callout_lock_enter(void) 131b6233ca5Sraf { 132b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 133a574db85Sraf cancel_safe_mutex_lock(&curthread->ul_uberdata->callout_lock); 134b6233ca5Sraf } 1357c478bd9Sstevel@tonic-gate 136b6233ca5Sraf void 13798c1a6b4Sraf callout_lock_exit(void) 138b6233ca5Sraf { 139b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 140a574db85Sraf cancel_safe_mutex_unlock(&curthread->ul_uberdata->callout_lock); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 143dfb96a4fSab pid_t 144*7257d1b4Sraf forkx(int flags) 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1477c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1487c478bd9Sstevel@tonic-gate pid_t pid; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 1537c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 1547c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 1557c478bd9Sstevel@tonic-gate * must never call fork(). 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 1587c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1597c478bd9Sstevel@tonic-gate return (-1); 1607c478bd9Sstevel@tonic-gate } 161657b1f3dSraf pid = __forkx(flags); 1627c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1638cd45542Sraf udp->pid = getpid(); 1647c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate return (pid); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1692e145884Sraf sigoff(self); 1702e145884Sraf if (self->ul_fork) { 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 1737c478bd9Sstevel@tonic-gate */ 1742e145884Sraf sigon(self); 1752e145884Sraf errno = EDEADLK; 1767c478bd9Sstevel@tonic-gate return (-1); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate self->ul_fork = 1; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 1827c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 1832e145884Sraf * internal lmutex_lock()-acquired locks while invoking them. 1842e145884Sraf * We hold only udp->atfork_lock to protect the atfork linkages. 1852e145884Sraf * If one of these pthread_atfork() functions attempts to fork 186b6233ca5Sraf * or to call pthread_atfork(), libc will detect the error and 187b6233ca5Sraf * fail the call with EDEADLK. Otherwise, the pthread_atfork() 188b6233ca5Sraf * functions are free to do anything they please (except they 189b6233ca5Sraf * will not receive any signals). 1907c478bd9Sstevel@tonic-gate */ 1918cd45542Sraf (void) mutex_lock(&udp->atfork_lock); 1927c478bd9Sstevel@tonic-gate _prefork_handler(); 1937c478bd9Sstevel@tonic-gate 1942e145884Sraf /* 1952e145884Sraf * Block every other thread attempting thr_suspend() or thr_continue(). 1962e145884Sraf */ 1978cd45542Sraf (void) mutex_lock(&udp->fork_lock); 1982e145884Sraf 1997c478bd9Sstevel@tonic-gate /* 2007c478bd9Sstevel@tonic-gate * Block all signals. 2012e145884Sraf * Just deferring them via sigoff() is not enough. 2027c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 203657b1f3dSraf * that was actually sent to the parent before __forkx(). 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate block_all_signals(self); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 2097c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 210b6233ca5Sraf * Thus, we are assured that no lmutex_lock()-acquired library 211b6233ca5Sraf * locks are held while we invoke fork() from the current thread. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate suspend_fork(); 2147c478bd9Sstevel@tonic-gate 215657b1f3dSraf pid = __forkx(flags); 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 2207c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 221657b1f3dSraf * Because we blocked all signals before __forkx(), a 2227c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 2237c478bd9Sstevel@tonic-gate */ 2247c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2257c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2267c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2277c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2288cd45542Sraf udp->pid = getpid(); 2297c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 230883492d5Sraf unregister_locks(); 231f841f6adSraf postfork1_child(); 2327c478bd9Sstevel@tonic-gate restore_signals(self); 2338cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 2347c478bd9Sstevel@tonic-gate _postfork_child_handler(); 2357c478bd9Sstevel@tonic-gate } else { 236657b1f3dSraf /* restart all threads that were suspended for fork() */ 2377c478bd9Sstevel@tonic-gate continue_fork(0); 2387c478bd9Sstevel@tonic-gate restore_signals(self); 2398cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 2407c478bd9Sstevel@tonic-gate _postfork_parent_handler(); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2438cd45542Sraf (void) mutex_unlock(&udp->atfork_lock); 2447c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2452e145884Sraf sigon(self); 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate return (pid); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* 251657b1f3dSraf * fork() is fork1() for both Posix threads and Solaris threads. 252657b1f3dSraf * The forkall() interface exists for applications that require 253657b1f3dSraf * the semantics of replicating all threads. 2547c478bd9Sstevel@tonic-gate */ 255*7257d1b4Sraf #pragma weak fork1 = fork 2567c478bd9Sstevel@tonic-gate pid_t 257*7257d1b4Sraf fork(void) 258657b1f3dSraf { 259*7257d1b4Sraf return (forkx(0)); 260657b1f3dSraf } 261657b1f3dSraf 262657b1f3dSraf /* 263657b1f3dSraf * Much of the logic here is the same as in forkx(). 264657b1f3dSraf * See the comments in forkx(), above. 265657b1f3dSraf */ 266dfb96a4fSab pid_t 267*7257d1b4Sraf forkallx(int flags) 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 2707c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 2717c478bd9Sstevel@tonic-gate pid_t pid; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 2747c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 2757c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2767c478bd9Sstevel@tonic-gate return (-1); 2777c478bd9Sstevel@tonic-gate } 278657b1f3dSraf pid = __forkallx(flags); 2797c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2808cd45542Sraf udp->pid = getpid(); 2817c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate return (pid); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2862e145884Sraf sigoff(self); 2872e145884Sraf if (self->ul_fork) { 2882e145884Sraf sigon(self); 2892e145884Sraf errno = EDEADLK; 2907c478bd9Sstevel@tonic-gate return (-1); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate self->ul_fork = 1; 2938cd45542Sraf (void) mutex_lock(&udp->atfork_lock); 2948cd45542Sraf (void) mutex_lock(&udp->fork_lock); 2957c478bd9Sstevel@tonic-gate block_all_signals(self); 2967c478bd9Sstevel@tonic-gate suspend_fork(); 2977c478bd9Sstevel@tonic-gate 298657b1f3dSraf pid = __forkallx(flags); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate if (pid == 0) { 3017c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 3027c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 3037c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 3047c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 3058cd45542Sraf udp->pid = getpid(); 306883492d5Sraf unregister_locks(); 3077c478bd9Sstevel@tonic-gate continue_fork(1); 3087c478bd9Sstevel@tonic-gate } else { 3097c478bd9Sstevel@tonic-gate continue_fork(0); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate restore_signals(self); 3128cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 3138cd45542Sraf (void) mutex_unlock(&udp->atfork_lock); 3142e145884Sraf self->ul_fork = 0; 3152e145884Sraf sigon(self); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate return (pid); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 320657b1f3dSraf pid_t 321*7257d1b4Sraf forkall(void) 322657b1f3dSraf { 323*7257d1b4Sraf return (forkallx(0)); 324657b1f3dSraf } 325657b1f3dSraf 3267c478bd9Sstevel@tonic-gate /* 327a574db85Sraf * For the implementation of cancellation at cancellation points. 3287c478bd9Sstevel@tonic-gate */ 3297c478bd9Sstevel@tonic-gate #define PROLOGUE \ 3307c478bd9Sstevel@tonic-gate { \ 3317c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 332a574db85Sraf int nocancel = \ 333a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \ 334a574db85Sraf self->ul_critical | self->ul_sigdefer); \ 335a574db85Sraf int abort = 0; \ 3367c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3377c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3387c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3397c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3407c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 341*7257d1b4Sraf pthread_exit(PTHREAD_CANCELED); \ 3427c478bd9Sstevel@tonic-gate } \ 3437c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 344a574db85Sraf } else if (self->ul_cancel_pending && \ 345a574db85Sraf !self->ul_cancel_disabled) { \ 346a574db85Sraf set_cancel_eintr_flag(self); \ 347a574db85Sraf abort = 1; \ 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate #define EPILOGUE \ 3517c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3527c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3537c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3547c478bd9Sstevel@tonic-gate } \ 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* 3587c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 3597c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 3607c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 3617c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 3627c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 3657c478bd9Sstevel@tonic-gate PROLOGUE \ 366a574db85Sraf if (abort) { \ 367a574db85Sraf *self->ul_errnop = EINTR; \ 368a574db85Sraf return (-1); \ 369a574db85Sraf } \ 3707c478bd9Sstevel@tonic-gate if (nocancel) \ 3717c478bd9Sstevel@tonic-gate return (function_call); \ 3727c478bd9Sstevel@tonic-gate rv = function_call; \ 3737c478bd9Sstevel@tonic-gate EPILOGUE \ 3747c478bd9Sstevel@tonic-gate return (rv); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 3787c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 3797c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 3807c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 3817c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 3827c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 3837c478bd9Sstevel@tonic-gate * for the particular signal. 3847c478bd9Sstevel@tonic-gate * 3857c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 3867c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 3877c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 3907c478bd9Sstevel@tonic-gate { \ 3917c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 392a574db85Sraf int nocancel = \ 393a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \ 394a574db85Sraf self->ul_critical | self->ul_sigdefer); \ 3957c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 3967c478bd9Sstevel@tonic-gate if (sigmask) { \ 3977c478bd9Sstevel@tonic-gate block_all_signals(self); \ 3980293487cSraf self->ul_tmpmask.__sigbits[0] = sigmask->__sigbits[0]; \ 3990293487cSraf self->ul_tmpmask.__sigbits[1] = sigmask->__sigbits[1]; \ 4007c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 4017c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 4027c478bd9Sstevel@tonic-gate } \ 4037c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4047c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 4057c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 4067c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 4077c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 4087c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4097c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 4107c478bd9Sstevel@tonic-gate restore_signals(self); \ 4117c478bd9Sstevel@tonic-gate } \ 412*7257d1b4Sraf pthread_exit(PTHREAD_CANCELED); \ 4137c478bd9Sstevel@tonic-gate } \ 4147c478bd9Sstevel@tonic-gate } \ 4157c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 4167c478bd9Sstevel@tonic-gate } \ 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 4217c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 4227c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 4237c478bd9Sstevel@tonic-gate * original signal mask ourself. 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 4267c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4277c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 4287c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 4297c478bd9Sstevel@tonic-gate } \ 4307c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4317c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 4327c478bd9Sstevel@tonic-gate restore_signals(self); \ 4337c478bd9Sstevel@tonic-gate } \ 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 43634709573Sraf /* 437f841f6adSraf * Cancellation prologue and epilogue functions, 438f841f6adSraf * for cancellation points too complex to include here. 43934709573Sraf */ 44034709573Sraf void 44134709573Sraf _cancel_prologue(void) 44234709573Sraf { 44334709573Sraf ulwp_t *self = curthread; 44434709573Sraf 445a574db85Sraf self->ul_cancel_prologue = 446a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | 447a574db85Sraf self->ul_critical | self->ul_sigdefer) != 0; 44834709573Sraf if (self->ul_cancel_prologue == 0) { 44934709573Sraf self->ul_save_async = self->ul_cancel_async; 45034709573Sraf if (!self->ul_cancel_disabled) { 45134709573Sraf self->ul_cancel_async = 1; 45234709573Sraf if (self->ul_cancel_pending) 453*7257d1b4Sraf pthread_exit(PTHREAD_CANCELED); 45434709573Sraf } 45534709573Sraf self->ul_sp = stkptr(); 456a574db85Sraf } else if (self->ul_cancel_pending && 457a574db85Sraf !self->ul_cancel_disabled) { 458a574db85Sraf set_cancel_eintr_flag(self); 45934709573Sraf } 46034709573Sraf } 46134709573Sraf 46234709573Sraf void 46334709573Sraf _cancel_epilogue(void) 46434709573Sraf { 46534709573Sraf ulwp_t *self = curthread; 46634709573Sraf 46734709573Sraf if (self->ul_cancel_prologue == 0) { 46834709573Sraf self->ul_sp = 0; 46934709573Sraf self->ul_cancel_async = self->ul_save_async; 47034709573Sraf } 47134709573Sraf } 47234709573Sraf 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 4757c478bd9Sstevel@tonic-gate */ 4767c478bd9Sstevel@tonic-gate int 4777c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 4787c478bd9Sstevel@tonic-gate { 4797c478bd9Sstevel@tonic-gate int error; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate PROLOGUE 482a574db85Sraf if (abort) 483a574db85Sraf return (EINTR); 484a574db85Sraf while ((error = __lwp_wait(tid, found)) == EINTR && !cancel_active()) 485a574db85Sraf continue; 4867c478bd9Sstevel@tonic-gate EPILOGUE 4877c478bd9Sstevel@tonic-gate return (error); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate ssize_t 491*7257d1b4Sraf read(int fd, void *buf, size_t size) 4927c478bd9Sstevel@tonic-gate { 493a574db85Sraf extern ssize_t __read(int, void *, size_t); 4947c478bd9Sstevel@tonic-gate ssize_t rv; 4957c478bd9Sstevel@tonic-gate 496a574db85Sraf PERFORM(__read(fd, buf, size)) 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate ssize_t 500*7257d1b4Sraf write(int fd, const void *buf, size_t size) 5017c478bd9Sstevel@tonic-gate { 502a574db85Sraf extern ssize_t __write(int, const void *, size_t); 5037c478bd9Sstevel@tonic-gate ssize_t rv; 5047c478bd9Sstevel@tonic-gate 505a574db85Sraf PERFORM(__write(fd, buf, size)) 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate int 509*7257d1b4Sraf getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5107c478bd9Sstevel@tonic-gate int *flagsp) 5117c478bd9Sstevel@tonic-gate { 512a574db85Sraf extern int __getmsg(int, struct strbuf *, struct strbuf *, int *); 5137c478bd9Sstevel@tonic-gate int rv; 5147c478bd9Sstevel@tonic-gate 515a574db85Sraf PERFORM(__getmsg(fd, ctlptr, dataptr, flagsp)) 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate int 519*7257d1b4Sraf getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5207c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 5217c478bd9Sstevel@tonic-gate { 522a574db85Sraf extern int __getpmsg(int, struct strbuf *, struct strbuf *, 5232e145884Sraf int *, int *); 5247c478bd9Sstevel@tonic-gate int rv; 5257c478bd9Sstevel@tonic-gate 526a574db85Sraf PERFORM(__getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate int 530*7257d1b4Sraf putmsg(int fd, const struct strbuf *ctlptr, 5317c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5327c478bd9Sstevel@tonic-gate { 533a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5342e145884Sraf const struct strbuf *, int); 5357c478bd9Sstevel@tonic-gate int rv; 5367c478bd9Sstevel@tonic-gate 537a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags)) 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate int 5417c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 5427c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5437c478bd9Sstevel@tonic-gate { 544a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5452e145884Sraf const struct strbuf *, int); 5467c478bd9Sstevel@tonic-gate int rv; 5477c478bd9Sstevel@tonic-gate 548a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate int 552*7257d1b4Sraf putpmsg(int fd, const struct strbuf *ctlptr, 5537c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5547c478bd9Sstevel@tonic-gate { 555a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5562e145884Sraf const struct strbuf *, int, int); 5577c478bd9Sstevel@tonic-gate int rv; 5587c478bd9Sstevel@tonic-gate 559a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags)) 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate int 5637c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 5647c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5657c478bd9Sstevel@tonic-gate { 566a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5672e145884Sraf const struct strbuf *, int, int); 5687c478bd9Sstevel@tonic-gate int rv; 5697c478bd9Sstevel@tonic-gate 570a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate int 574*7257d1b4Sraf nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 5757c478bd9Sstevel@tonic-gate { 5767c478bd9Sstevel@tonic-gate int error; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate PROLOGUE 579a574db85Sraf error = abort? EINTR : __nanosleep(rqtp, rmtp); 5807c478bd9Sstevel@tonic-gate EPILOGUE 5817c478bd9Sstevel@tonic-gate if (error) { 5827c478bd9Sstevel@tonic-gate errno = error; 5837c478bd9Sstevel@tonic-gate return (-1); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate return (0); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate int 589*7257d1b4Sraf clock_nanosleep(clockid_t clock_id, int flags, 5907c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 5917c478bd9Sstevel@tonic-gate { 5927c478bd9Sstevel@tonic-gate timespec_t reltime; 5937c478bd9Sstevel@tonic-gate hrtime_t start; 5947c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 5957c478bd9Sstevel@tonic-gate hrtime_t lapse; 5967c478bd9Sstevel@tonic-gate int error; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate switch (clock_id) { 5997c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 6007c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 6017c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 6027c478bd9Sstevel@tonic-gate return (ENOTSUP); 6037c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 6047c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 6057c478bd9Sstevel@tonic-gate break; 6067c478bd9Sstevel@tonic-gate default: 6077c478bd9Sstevel@tonic-gate return (EINVAL); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6107c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6117c478bd9Sstevel@tonic-gate rmtp = NULL; 6127c478bd9Sstevel@tonic-gate } else { 6137c478bd9Sstevel@tonic-gate reltime = *rqtp; 6147c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 6157c478bd9Sstevel@tonic-gate start = gethrtime(); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate restart: 6187c478bd9Sstevel@tonic-gate PROLOGUE 619a574db85Sraf error = abort? EINTR : __nanosleep(&reltime, rmtp); 6207c478bd9Sstevel@tonic-gate EPILOGUE 6217c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 6227c478bd9Sstevel@tonic-gate /* 6237c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 6247c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 6257c478bd9Sstevel@tonic-gate * the system clock. 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6287c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6297c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 6307c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6317c478bd9Sstevel@tonic-gate goto restart; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate } else { 6347c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6352e145884Sraf rqtp->tv_nsec; 6367c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 6377c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 6387c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 6397c478bd9Sstevel@tonic-gate goto restart; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 6447c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 6477c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 6487c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 6497c478bd9Sstevel@tonic-gate * 6507c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 6517c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 6527c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 6537c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 6547c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 6557c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6587c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 6597c478bd9Sstevel@tonic-gate goto restart; 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate return (error); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate unsigned int 665*7257d1b4Sraf sleep(unsigned int sec) 6667c478bd9Sstevel@tonic-gate { 6677c478bd9Sstevel@tonic-gate unsigned int rem = 0; 6687c478bd9Sstevel@tonic-gate timespec_t ts; 6697c478bd9Sstevel@tonic-gate timespec_t tsr; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 6727c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 673*7257d1b4Sraf if (nanosleep(&ts, &tsr) == -1 && errno == EINTR) { 6747c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 6757c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 6767c478bd9Sstevel@tonic-gate rem++; 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate return (rem); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate int 682*7257d1b4Sraf usleep(useconds_t usec) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate timespec_t ts; 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 6877c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 688*7257d1b4Sraf (void) nanosleep(&ts, NULL); 6897c478bd9Sstevel@tonic-gate return (0); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate int 693*7257d1b4Sraf close(int fildes) 6947c478bd9Sstevel@tonic-gate { 695f841f6adSraf extern void _aio_close(int); 696a574db85Sraf extern int __close(int); 6977c478bd9Sstevel@tonic-gate int rv; 6987c478bd9Sstevel@tonic-gate 699720d4a35Sraf /* 700720d4a35Sraf * If we call _aio_close() while in a critical region, 701720d4a35Sraf * we will draw an ASSERT() failure, so don't do it. 702720d4a35Sraf * No calls to close() from within libc need _aio_close(); 703720d4a35Sraf * only the application's calls to close() need this, 704720d4a35Sraf * and such calls are never from a libc critical region. 705720d4a35Sraf */ 706720d4a35Sraf if (curthread->ul_critical == 0) 707720d4a35Sraf _aio_close(fildes); 708a574db85Sraf PERFORM(__close(fildes)) 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate int 712*7257d1b4Sraf creat(const char *path, mode_t mode) 7137c478bd9Sstevel@tonic-gate { 714a574db85Sraf extern int __creat(const char *, mode_t); 7157c478bd9Sstevel@tonic-gate int rv; 7167c478bd9Sstevel@tonic-gate 717a574db85Sraf PERFORM(__creat(path, mode)) 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7217c478bd9Sstevel@tonic-gate int 722*7257d1b4Sraf creat64(const char *path, mode_t mode) 7237c478bd9Sstevel@tonic-gate { 724a574db85Sraf extern int __creat64(const char *, mode_t); 7257c478bd9Sstevel@tonic-gate int rv; 7267c478bd9Sstevel@tonic-gate 727a574db85Sraf PERFORM(__creat64(path, mode)) 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7307c478bd9Sstevel@tonic-gate 731a574db85Sraf int 732*7257d1b4Sraf 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 741*7257d1b4Sraf 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 757*7257d1b4Sraf 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 766*7257d1b4Sraf 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 775*7257d1b4Sraf 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 785*7257d1b4Sraf 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 795*7257d1b4Sraf 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 804*7257d1b4Sraf 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 813*7257d1b4Sraf 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 822*7257d1b4Sraf open(const char *path, int oflag, ...) 8237c478bd9Sstevel@tonic-gate { 824a574db85Sraf extern int __open(const char *, int, ...); 825a574db85Sraf mode_t mode; 8267c478bd9Sstevel@tonic-gate int rv; 827a574db85Sraf va_list ap; 8287c478bd9Sstevel@tonic-gate 829a574db85Sraf va_start(ap, oflag); 830a574db85Sraf mode = va_arg(ap, mode_t); 831a574db85Sraf va_end(ap); 832a574db85Sraf PERFORM(__open(path, oflag, mode)) 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate int 836*7257d1b4Sraf openat(int fd, const char *path, int oflag, ...) 8377c478bd9Sstevel@tonic-gate { 838a574db85Sraf extern int __openat(int, const char *, int, ...); 8397c478bd9Sstevel@tonic-gate mode_t mode; 8407c478bd9Sstevel@tonic-gate int rv; 8417c478bd9Sstevel@tonic-gate va_list ap; 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8447c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8457c478bd9Sstevel@tonic-gate va_end(ap); 846a574db85Sraf PERFORM(__openat(fd, path, oflag, mode)) 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate #if !defined(_LP64) 850a574db85Sraf int 851*7257d1b4Sraf open64(const char *path, int oflag, ...) 852a574db85Sraf { 853a574db85Sraf extern int __open64(const char *, int, ...); 854a574db85Sraf mode_t mode; 855a574db85Sraf int rv; 856a574db85Sraf va_list ap; 857a574db85Sraf 858a574db85Sraf va_start(ap, oflag); 859a574db85Sraf mode = va_arg(ap, mode_t); 860a574db85Sraf va_end(ap); 861a574db85Sraf PERFORM(__open64(path, oflag, mode)) 862a574db85Sraf } 863a574db85Sraf 8647c478bd9Sstevel@tonic-gate int 865*7257d1b4Sraf openat64(int fd, const char *path, int oflag, ...) 8667c478bd9Sstevel@tonic-gate { 867a574db85Sraf extern int __openat64(int, const char *, int, ...); 8687c478bd9Sstevel@tonic-gate mode_t mode; 8697c478bd9Sstevel@tonic-gate int rv; 8707c478bd9Sstevel@tonic-gate va_list ap; 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8737c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8747c478bd9Sstevel@tonic-gate va_end(ap); 875a574db85Sraf PERFORM(__openat64(fd, path, oflag, mode)) 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate int 880*7257d1b4Sraf pause(void) 8817c478bd9Sstevel@tonic-gate { 882a574db85Sraf extern int __pause(void); 8837c478bd9Sstevel@tonic-gate int rv; 8847c478bd9Sstevel@tonic-gate 885a574db85Sraf PERFORM(__pause()) 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate ssize_t 889*7257d1b4Sraf pread(int fildes, void *buf, size_t nbyte, off_t offset) 8907c478bd9Sstevel@tonic-gate { 891a574db85Sraf extern ssize_t __pread(int, void *, size_t, off_t); 8927c478bd9Sstevel@tonic-gate ssize_t rv; 8937c478bd9Sstevel@tonic-gate 894a574db85Sraf PERFORM(__pread(fildes, buf, nbyte, offset)) 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate #if !defined(_LP64) 8987c478bd9Sstevel@tonic-gate ssize_t 899*7257d1b4Sraf pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 9007c478bd9Sstevel@tonic-gate { 901a574db85Sraf extern ssize_t __pread64(int, void *, size_t, off64_t); 9027c478bd9Sstevel@tonic-gate ssize_t rv; 9037c478bd9Sstevel@tonic-gate 904a574db85Sraf PERFORM(__pread64(fildes, buf, nbyte, offset)) 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate ssize_t 909*7257d1b4Sraf pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 9107c478bd9Sstevel@tonic-gate { 911a574db85Sraf extern ssize_t __pwrite(int, const void *, size_t, off_t); 9127c478bd9Sstevel@tonic-gate ssize_t rv; 9137c478bd9Sstevel@tonic-gate 914a574db85Sraf PERFORM(__pwrite(fildes, buf, nbyte, offset)) 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate #if !defined(_LP64) 9187c478bd9Sstevel@tonic-gate ssize_t 919*7257d1b4Sraf pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 9207c478bd9Sstevel@tonic-gate { 921a574db85Sraf extern ssize_t __pwrite64(int, const void *, size_t, off64_t); 9227c478bd9Sstevel@tonic-gate ssize_t rv; 9237c478bd9Sstevel@tonic-gate 924a574db85Sraf PERFORM(__pwrite64(fildes, buf, nbyte, offset)) 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate ssize_t 929*7257d1b4Sraf readv(int fildes, const struct iovec *iov, int iovcnt) 9307c478bd9Sstevel@tonic-gate { 931a574db85Sraf extern ssize_t __readv(int, const struct iovec *, int); 9327c478bd9Sstevel@tonic-gate ssize_t rv; 9337c478bd9Sstevel@tonic-gate 934a574db85Sraf PERFORM(__readv(fildes, iov, iovcnt)) 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate int 938*7257d1b4Sraf sigpause(int sig) 9397c478bd9Sstevel@tonic-gate { 940a574db85Sraf extern int __sigpause(int); 9417c478bd9Sstevel@tonic-gate int rv; 9427c478bd9Sstevel@tonic-gate 943a574db85Sraf PERFORM(__sigpause(sig)) 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate int 947*7257d1b4Sraf sigsuspend(const sigset_t *set) 9487c478bd9Sstevel@tonic-gate { 9497c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 9507c478bd9Sstevel@tonic-gate int rv; 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 9537c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 9547c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9557c478bd9Sstevel@tonic-gate return (rv); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate int 9597c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 9607c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 9617c478bd9Sstevel@tonic-gate { 9627c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 9632e145884Sraf const sigset_t *); 9647c478bd9Sstevel@tonic-gate int rv; 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 9677c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 9687c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9697c478bd9Sstevel@tonic-gate return (rv); 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate int 973*7257d1b4Sraf sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout) 9747c478bd9Sstevel@tonic-gate { 975f841f6adSraf extern int __sigtimedwait(const sigset_t *, siginfo_t *, 9762e145884Sraf const timespec_t *); 9777c478bd9Sstevel@tonic-gate siginfo_t info; 9787c478bd9Sstevel@tonic-gate int sig; 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate PROLOGUE 981a574db85Sraf if (abort) { 982a574db85Sraf *self->ul_errnop = EINTR; 9837c478bd9Sstevel@tonic-gate sig = -1; 984a574db85Sraf } else { 985a574db85Sraf sig = __sigtimedwait(set, &info, timeout); 986a574db85Sraf if (sig == SIGCANCEL && 987a574db85Sraf (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 988a574db85Sraf do_sigcancel(); 989a574db85Sraf *self->ul_errnop = EINTR; 990a574db85Sraf sig = -1; 991a574db85Sraf } 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate EPILOGUE 9947c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 9958cd45542Sraf (void) memcpy(infop, &info, sizeof (*infop)); 9967c478bd9Sstevel@tonic-gate return (sig); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate int 1000*7257d1b4Sraf sigwait(sigset_t *set) 10017c478bd9Sstevel@tonic-gate { 1002*7257d1b4Sraf return (sigtimedwait(set, NULL, NULL)); 1003f841f6adSraf } 1004f841f6adSraf 1005f841f6adSraf int 1006*7257d1b4Sraf sigwaitinfo(const sigset_t *set, siginfo_t *info) 1007f841f6adSraf { 1008*7257d1b4Sraf return (sigtimedwait(set, info, NULL)); 1009f841f6adSraf } 1010f841f6adSraf 1011f841f6adSraf int 1012*7257d1b4Sraf sigqueue(pid_t pid, int signo, const union sigval value) 1013f841f6adSraf { 1014f841f6adSraf extern int __sigqueue(pid_t pid, int signo, 10152e145884Sraf /* const union sigval */ void *value, int si_code, int block); 1016f841f6adSraf return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0)); 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate int 1020a574db85Sraf _so_accept(int sock, struct sockaddr *addr, uint_t *addrlen, int version) 10217c478bd9Sstevel@tonic-gate { 1022a574db85Sraf extern int __so_accept(int, struct sockaddr *, uint_t *, int); 10237c478bd9Sstevel@tonic-gate int rv; 10247c478bd9Sstevel@tonic-gate 1025a574db85Sraf PERFORM(__so_accept(sock, addr, addrlen, version)) 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 1028a574db85Sraf int 1029a574db85Sraf _so_connect(int sock, struct sockaddr *addr, uint_t addrlen, int version) 10307c478bd9Sstevel@tonic-gate { 1031a574db85Sraf extern int __so_connect(int, struct sockaddr *, uint_t, int); 1032a574db85Sraf int rv; 10337c478bd9Sstevel@tonic-gate 1034a574db85Sraf PERFORM(__so_connect(sock, addr, addrlen, version)) 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 1037a574db85Sraf int 1038a574db85Sraf _so_recv(int sock, void *buf, size_t len, int flags) 10397c478bd9Sstevel@tonic-gate { 1040a574db85Sraf extern int __so_recv(int, void *, size_t, int); 1041a574db85Sraf int rv; 10427c478bd9Sstevel@tonic-gate 1043a574db85Sraf PERFORM(__so_recv(sock, buf, len, flags)) 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate int 1047a574db85Sraf _so_recvfrom(int sock, void *buf, size_t len, int flags, 1048a574db85Sraf struct sockaddr *addr, int *addrlen) 10497c478bd9Sstevel@tonic-gate { 1050a574db85Sraf extern int __so_recvfrom(int, void *, size_t, int, 1051a574db85Sraf struct sockaddr *, int *); 10527c478bd9Sstevel@tonic-gate int rv; 10537c478bd9Sstevel@tonic-gate 1054a574db85Sraf PERFORM(__so_recvfrom(sock, buf, len, flags, addr, addrlen)) 10557c478bd9Sstevel@tonic-gate } 10567c478bd9Sstevel@tonic-gate 1057a574db85Sraf int 1058a574db85Sraf _so_recvmsg(int sock, struct msghdr *msg, int flags) 1059a574db85Sraf { 1060a574db85Sraf extern int __so_recvmsg(int, struct msghdr *, int); 1061a574db85Sraf int rv; 1062a574db85Sraf 1063a574db85Sraf PERFORM(__so_recvmsg(sock, msg, flags)) 1064a574db85Sraf } 1065a574db85Sraf 1066a574db85Sraf int 1067a574db85Sraf _so_send(int sock, const void *buf, size_t len, int flags) 1068a574db85Sraf { 1069a574db85Sraf extern int __so_send(int, const void *, size_t, int); 1070a574db85Sraf int rv; 1071a574db85Sraf 1072a574db85Sraf PERFORM(__so_send(sock, buf, len, flags)) 1073a574db85Sraf } 1074a574db85Sraf 1075a574db85Sraf int 1076a574db85Sraf _so_sendmsg(int sock, const struct msghdr *msg, int flags) 10777c478bd9Sstevel@tonic-gate { 1078a574db85Sraf extern int __so_sendmsg(int, const struct msghdr *, int); 1079a574db85Sraf int rv; 1080a574db85Sraf 1081a574db85Sraf PERFORM(__so_sendmsg(sock, msg, flags)) 1082a574db85Sraf } 1083a574db85Sraf 1084a574db85Sraf int 1085a574db85Sraf _so_sendto(int sock, const void *buf, size_t len, int flags, 1086a574db85Sraf const struct sockaddr *addr, int *addrlen) 1087a574db85Sraf { 1088a574db85Sraf extern int __so_sendto(int, const void *, size_t, int, 1089a574db85Sraf const struct sockaddr *, int *); 1090a574db85Sraf int rv; 1091a574db85Sraf 1092a574db85Sraf PERFORM(__so_sendto(sock, buf, len, flags, addr, addrlen)) 1093a574db85Sraf } 1094a574db85Sraf 1095a574db85Sraf int 1096*7257d1b4Sraf tcdrain(int fildes) 1097a574db85Sraf { 1098a574db85Sraf extern int __tcdrain(int); 1099a574db85Sraf int rv; 1100a574db85Sraf 1101a574db85Sraf PERFORM(__tcdrain(fildes)) 1102a574db85Sraf } 1103a574db85Sraf 1104a574db85Sraf int 1105*7257d1b4Sraf waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 1106a574db85Sraf { 1107a574db85Sraf extern int __waitid(idtype_t, id_t, siginfo_t *, int); 1108a574db85Sraf int rv; 11097c478bd9Sstevel@tonic-gate 1110a574db85Sraf if (options & WNOHANG) 1111a574db85Sraf return (__waitid(idtype, id, infop, options)); 1112a574db85Sraf PERFORM(__waitid(idtype, id, infop, options)) 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate ssize_t 1116*7257d1b4Sraf writev(int fildes, const struct iovec *iov, int iovcnt) 11177c478bd9Sstevel@tonic-gate { 1118a574db85Sraf extern ssize_t __writev(int, const struct iovec *, int); 11197c478bd9Sstevel@tonic-gate ssize_t rv; 11207c478bd9Sstevel@tonic-gate 1121a574db85Sraf PERFORM(__writev(fildes, iov, iovcnt)) 11227c478bd9Sstevel@tonic-gate } 1123