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 /* 2309ce0d4aSRoger A. Faulkner * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include "lint.h" 287c478bd9Sstevel@tonic-gate #include "thr_uberdata.h" 297c478bd9Sstevel@tonic-gate #include <stdarg.h> 307c478bd9Sstevel@tonic-gate #include <poll.h> 317c478bd9Sstevel@tonic-gate #include <stropts.h> 327c478bd9Sstevel@tonic-gate #include <dlfcn.h> 33a574db85Sraf #include <wait.h> 34a574db85Sraf #include <sys/socket.h> 357c478bd9Sstevel@tonic-gate #include <sys/uio.h> 36a574db85Sraf #include <sys/file.h> 37a574db85Sraf #include <sys/door.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407257d1b4Sraf * These leading-underbar symbols exist because mistakes were made 417257d1b4Sraf * in the past that put them into non-SUNWprivate versions of 427257d1b4Sraf * the libc mapfiles. They should be eliminated, but oh well... 437257d1b4Sraf */ 447257d1b4Sraf #pragma weak _fork = fork 457257d1b4Sraf #pragma weak _read = read 467257d1b4Sraf #pragma weak _write = write 477257d1b4Sraf #pragma weak _getmsg = getmsg 487257d1b4Sraf #pragma weak _getpmsg = getpmsg 497257d1b4Sraf #pragma weak _putmsg = putmsg 507257d1b4Sraf #pragma weak _putpmsg = putpmsg 517257d1b4Sraf #pragma weak _sleep = sleep 527257d1b4Sraf #pragma weak _close = close 537257d1b4Sraf #pragma weak _creat = creat 547257d1b4Sraf #pragma weak _fcntl = fcntl 557257d1b4Sraf #pragma weak _fsync = fsync 567257d1b4Sraf #pragma weak _lockf = lockf 577257d1b4Sraf #pragma weak _msgrcv = msgrcv 587257d1b4Sraf #pragma weak _msgsnd = msgsnd 597257d1b4Sraf #pragma weak _msync = msync 607257d1b4Sraf #pragma weak _open = open 617257d1b4Sraf #pragma weak _openat = openat 627257d1b4Sraf #pragma weak _pause = pause 637257d1b4Sraf #pragma weak _readv = readv 647257d1b4Sraf #pragma weak _sigpause = sigpause 657257d1b4Sraf #pragma weak _sigsuspend = sigsuspend 667257d1b4Sraf #pragma weak _tcdrain = tcdrain 677257d1b4Sraf #pragma weak _waitid = waitid 687257d1b4Sraf #pragma weak _writev = writev 697257d1b4Sraf 707257d1b4Sraf #if !defined(_LP64) 717257d1b4Sraf #pragma weak _creat64 = creat64 727257d1b4Sraf #pragma weak _lockf64 = lockf64 737257d1b4Sraf #pragma weak _open64 = open64 747257d1b4Sraf #pragma weak _openat64 = openat64 757257d1b4Sraf #pragma weak _pread64 = pread64 767257d1b4Sraf #pragma weak _pwrite64 = pwrite64 777257d1b4Sraf #endif 787257d1b4Sraf 797257d1b4Sraf /* 80d56c62ccSraf * These are SUNWprivate, but they are being used by Sun Studio libcollector. 81d56c62ccSraf */ 82d56c62ccSraf #pragma weak _fork1 = fork1 83d56c62ccSraf #pragma weak _forkall = forkall 84d56c62ccSraf 85d56c62ccSraf /* 8698c1a6b4Sraf * atfork_lock protects the pthread_atfork() data structures. 8798c1a6b4Sraf * 88b6233ca5Sraf * fork_lock does double-duty. Not only does it (and atfork_lock) 89b6233ca5Sraf * serialize calls to fork() and forkall(), but it also serializes calls 90b6233ca5Sraf * to thr_suspend() and thr_continue() (because fork() and forkall() also 91b6233ca5Sraf * suspend and continue other threads and they want no competition). 92b6233ca5Sraf * 9398c1a6b4Sraf * Functions called in dlopen()ed L10N objects can do anything, including 9498c1a6b4Sraf * call malloc() and free(). Such calls are not fork-safe when protected 9598c1a6b4Sraf * by an ordinary mutex that is acquired in libc's prefork processing 9698c1a6b4Sraf * because, with an interposed malloc library present, there would be a 9798c1a6b4Sraf * lock ordering violation due to the pthread_atfork() prefork function 9898c1a6b4Sraf * in the interposition library acquiring its malloc lock(s) before the 99b6233ca5Sraf * ordinary mutex in libc being acquired by libc's prefork functions. 100b6233ca5Sraf * 10198c1a6b4Sraf * Within libc, calls to malloc() and free() are fork-safe if the calls 10298c1a6b4Sraf * are made while holding no other libc locks. This covers almost all 10398c1a6b4Sraf * of libc's malloc() and free() calls. For those libc code paths, such 10498c1a6b4Sraf * as the above-mentioned L10N calls, that require serialization and that 10598c1a6b4Sraf * may call malloc() or free(), libc uses callout_lock_enter() to perform 10698c1a6b4Sraf * the serialization. This works because callout_lock is not acquired as 10798c1a6b4Sraf * part of running the pthread_atfork() prefork handlers (to avoid the 10898c1a6b4Sraf * lock ordering violation described above). Rather, it is simply 10998c1a6b4Sraf * reinitialized in postfork1_child() to cover the case that some 11098c1a6b4Sraf * now-defunct thread might have been suspended while holding it. 1117c478bd9Sstevel@tonic-gate */ 112b6233ca5Sraf 1132e145884Sraf void 1142e145884Sraf fork_lock_enter(void) 1157c478bd9Sstevel@tonic-gate { 116b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 1178cd45542Sraf (void) mutex_lock(&curthread->ul_uberdata->fork_lock); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate void 1217c478bd9Sstevel@tonic-gate fork_lock_exit(void) 1227c478bd9Sstevel@tonic-gate { 123b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 1248cd45542Sraf (void) mutex_unlock(&curthread->ul_uberdata->fork_lock); 125b6233ca5Sraf } 1267c478bd9Sstevel@tonic-gate 127a574db85Sraf /* 128a574db85Sraf * Use cancel_safe_mutex_lock() to protect against being cancelled while 129a574db85Sraf * holding callout_lock and calling outside of libc (via L10N plugins). 130a574db85Sraf * We will honor a pending cancellation request when callout_lock_exit() 131a574db85Sraf * is called, by calling cancel_safe_mutex_unlock(). 132a574db85Sraf */ 133b6233ca5Sraf void 13498c1a6b4Sraf callout_lock_enter(void) 135b6233ca5Sraf { 136b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 137a574db85Sraf cancel_safe_mutex_lock(&curthread->ul_uberdata->callout_lock); 138b6233ca5Sraf } 139b6233ca5Sraf 140b6233ca5Sraf void 14198c1a6b4Sraf callout_lock_exit(void) 142b6233ca5Sraf { 143b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 144a574db85Sraf cancel_safe_mutex_unlock(&curthread->ul_uberdata->callout_lock); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 147dfb96a4fSab196087 pid_t 1487257d1b4Sraf forkx(int flags) 1497c478bd9Sstevel@tonic-gate { 1507c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1517c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1527c478bd9Sstevel@tonic-gate pid_t pid; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 1557c478bd9Sstevel@tonic-gate /* 1567c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 1577c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 1587c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 1597c478bd9Sstevel@tonic-gate * must never call fork(). 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 1627c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1637c478bd9Sstevel@tonic-gate return (-1); 1647c478bd9Sstevel@tonic-gate } 165657b1f3dSraf pid = __forkx(flags); 1667c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1678cd45542Sraf udp->pid = getpid(); 1687c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate return (pid); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1732e145884Sraf sigoff(self); 1742e145884Sraf if (self->ul_fork) { 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 1777c478bd9Sstevel@tonic-gate */ 1782e145884Sraf sigon(self); 1792e145884Sraf errno = EDEADLK; 1807c478bd9Sstevel@tonic-gate return (-1); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate self->ul_fork = 1; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 1867c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 1872e145884Sraf * internal lmutex_lock()-acquired locks while invoking them. 1882e145884Sraf * We hold only udp->atfork_lock to protect the atfork linkages. 1892e145884Sraf * If one of these pthread_atfork() functions attempts to fork 190b6233ca5Sraf * or to call pthread_atfork(), libc will detect the error and 191b6233ca5Sraf * fail the call with EDEADLK. Otherwise, the pthread_atfork() 192b6233ca5Sraf * functions are free to do anything they please (except they 193b6233ca5Sraf * will not receive any signals). 1947c478bd9Sstevel@tonic-gate */ 1958cd45542Sraf (void) mutex_lock(&udp->atfork_lock); 1963771f298SRoger A. Faulkner 1973771f298SRoger A. Faulkner /* 1983771f298SRoger A. Faulkner * Posix (SUSv3) requires fork() to be async-signal-safe. 1993771f298SRoger A. Faulkner * This cannot be made to happen with fork handlers in place 2003771f298SRoger A. Faulkner * (they grab locks). To be in nominal compliance, don't run 2013771f298SRoger A. Faulkner * any fork handlers if we are called within a signal context. 2023771f298SRoger A. Faulkner * This leaves the child process in a questionable state with 2033771f298SRoger A. Faulkner * respect to its locks, but at least the parent process does 2043771f298SRoger A. Faulkner * not become deadlocked due to the calling thread attempting 2053771f298SRoger A. Faulkner * to acquire a lock that it already owns. 2063771f298SRoger A. Faulkner */ 2073771f298SRoger A. Faulkner if (self->ul_siglink == NULL) 2087c478bd9Sstevel@tonic-gate _prefork_handler(); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2112e145884Sraf * Block every other thread attempting thr_suspend() or thr_continue(). 2122e145884Sraf */ 2138cd45542Sraf (void) mutex_lock(&udp->fork_lock); 2142e145884Sraf 2152e145884Sraf /* 2167c478bd9Sstevel@tonic-gate * Block all signals. 2172e145884Sraf * Just deferring them via sigoff() is not enough. 2187c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 219657b1f3dSraf * that was actually sent to the parent before __forkx(). 2207c478bd9Sstevel@tonic-gate */ 2217c478bd9Sstevel@tonic-gate block_all_signals(self); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 2257c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 226b6233ca5Sraf * Thus, we are assured that no lmutex_lock()-acquired library 227b6233ca5Sraf * locks are held while we invoke fork() from the current thread. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate suspend_fork(); 2307c478bd9Sstevel@tonic-gate 231657b1f3dSraf pid = __forkx(flags); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 2367c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 237657b1f3dSraf * Because we blocked all signals before __forkx(), a 2387c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2417c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2427c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2437c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2448cd45542Sraf udp->pid = getpid(); 2457c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 246*c242ec1bSRoger A. Faulkner unregister_locks(); 247f841f6adSraf postfork1_child(); 2487c478bd9Sstevel@tonic-gate restore_signals(self); 2498cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 2503771f298SRoger A. Faulkner if (self->ul_siglink == NULL) 2517c478bd9Sstevel@tonic-gate _postfork_child_handler(); 2527c478bd9Sstevel@tonic-gate } else { 253657b1f3dSraf /* restart all threads that were suspended for fork() */ 2547c478bd9Sstevel@tonic-gate continue_fork(0); 2557c478bd9Sstevel@tonic-gate restore_signals(self); 2568cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 2573771f298SRoger A. Faulkner if (self->ul_siglink == NULL) 2587c478bd9Sstevel@tonic-gate _postfork_parent_handler(); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2618cd45542Sraf (void) mutex_unlock(&udp->atfork_lock); 2627c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2632e145884Sraf sigon(self); 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate return (pid); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate /* 269657b1f3dSraf * fork() is fork1() for both Posix threads and Solaris threads. 270657b1f3dSraf * The forkall() interface exists for applications that require 271657b1f3dSraf * the semantics of replicating all threads. 2727c478bd9Sstevel@tonic-gate */ 2737257d1b4Sraf #pragma weak fork1 = fork 2747c478bd9Sstevel@tonic-gate pid_t 2757257d1b4Sraf fork(void) 276657b1f3dSraf { 2777257d1b4Sraf return (forkx(0)); 278657b1f3dSraf } 279657b1f3dSraf 280657b1f3dSraf /* 281657b1f3dSraf * Much of the logic here is the same as in forkx(). 282657b1f3dSraf * See the comments in forkx(), above. 283657b1f3dSraf */ 284dfb96a4fSab196087 pid_t 2857257d1b4Sraf forkallx(int flags) 2867c478bd9Sstevel@tonic-gate { 2877c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 2887c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 2897c478bd9Sstevel@tonic-gate pid_t pid; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 2927c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 2937c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2947c478bd9Sstevel@tonic-gate return (-1); 2957c478bd9Sstevel@tonic-gate } 296657b1f3dSraf pid = __forkallx(flags); 2977c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2988cd45542Sraf udp->pid = getpid(); 2997c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate return (pid); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3042e145884Sraf sigoff(self); 3052e145884Sraf if (self->ul_fork) { 3062e145884Sraf sigon(self); 3072e145884Sraf errno = EDEADLK; 3087c478bd9Sstevel@tonic-gate return (-1); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate self->ul_fork = 1; 3118cd45542Sraf (void) mutex_lock(&udp->atfork_lock); 3128cd45542Sraf (void) mutex_lock(&udp->fork_lock); 3137c478bd9Sstevel@tonic-gate block_all_signals(self); 3147c478bd9Sstevel@tonic-gate suspend_fork(); 3157c478bd9Sstevel@tonic-gate 316657b1f3dSraf pid = __forkallx(flags); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate if (pid == 0) { 3197c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 3207c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 3217c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 3227c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 3238cd45542Sraf udp->pid = getpid(); 324*c242ec1bSRoger A. Faulkner unregister_locks(); 3257c478bd9Sstevel@tonic-gate continue_fork(1); 3267c478bd9Sstevel@tonic-gate } else { 3277c478bd9Sstevel@tonic-gate continue_fork(0); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate restore_signals(self); 3308cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 3318cd45542Sraf (void) mutex_unlock(&udp->atfork_lock); 3322e145884Sraf self->ul_fork = 0; 3332e145884Sraf sigon(self); 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate return (pid); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 338657b1f3dSraf pid_t 3397257d1b4Sraf forkall(void) 340657b1f3dSraf { 3417257d1b4Sraf return (forkallx(0)); 342657b1f3dSraf } 343657b1f3dSraf 3447c478bd9Sstevel@tonic-gate /* 345a574db85Sraf * For the implementation of cancellation at cancellation points. 3467c478bd9Sstevel@tonic-gate */ 3477c478bd9Sstevel@tonic-gate #define PROLOGUE \ 3487c478bd9Sstevel@tonic-gate { \ 3497c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 350a574db85Sraf int nocancel = \ 351a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \ 352a574db85Sraf self->ul_critical | self->ul_sigdefer); \ 353a574db85Sraf int abort = 0; \ 3547c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3557c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3567c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3577c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3587c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 3597257d1b4Sraf pthread_exit(PTHREAD_CANCELED); \ 3607c478bd9Sstevel@tonic-gate } \ 3617c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 362a574db85Sraf } else if (self->ul_cancel_pending && \ 363a574db85Sraf !self->ul_cancel_disabled) { \ 364a574db85Sraf set_cancel_eintr_flag(self); \ 365a574db85Sraf abort = 1; \ 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate #define EPILOGUE \ 3697c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3707c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3717c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3727c478bd9Sstevel@tonic-gate } \ 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate /* 3767c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 3777c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 3787c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 3797c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 3807c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 3837c478bd9Sstevel@tonic-gate PROLOGUE \ 384a574db85Sraf if (abort) { \ 385a574db85Sraf *self->ul_errnop = EINTR; \ 386a574db85Sraf return (-1); \ 387a574db85Sraf } \ 3887c478bd9Sstevel@tonic-gate if (nocancel) \ 3897c478bd9Sstevel@tonic-gate return (function_call); \ 3907c478bd9Sstevel@tonic-gate rv = function_call; \ 3917c478bd9Sstevel@tonic-gate EPILOGUE \ 3927c478bd9Sstevel@tonic-gate return (rv); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 3967c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 3977c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 3987c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 3997c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 4007c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 4017c478bd9Sstevel@tonic-gate * for the particular signal. 4027c478bd9Sstevel@tonic-gate * 4037c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 4047c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 4057c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 4087c478bd9Sstevel@tonic-gate { \ 4097c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 410a574db85Sraf int nocancel = \ 411a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \ 412a574db85Sraf self->ul_critical | self->ul_sigdefer); \ 4137c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 4147c478bd9Sstevel@tonic-gate if (sigmask) { \ 4157c478bd9Sstevel@tonic-gate block_all_signals(self); \ 4160293487cSraf self->ul_tmpmask.__sigbits[0] = sigmask->__sigbits[0]; \ 4170293487cSraf self->ul_tmpmask.__sigbits[1] = sigmask->__sigbits[1]; \ 4187c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 4197c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 4207c478bd9Sstevel@tonic-gate } \ 4217c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4227c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 4237c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 4247c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 4257c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 4267c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4277c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 4287c478bd9Sstevel@tonic-gate restore_signals(self); \ 4297c478bd9Sstevel@tonic-gate } \ 4307257d1b4Sraf pthread_exit(PTHREAD_CANCELED); \ 4317c478bd9Sstevel@tonic-gate } \ 4327c478bd9Sstevel@tonic-gate } \ 4337c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 4347c478bd9Sstevel@tonic-gate } \ 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 4397c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 4407c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 4417c478bd9Sstevel@tonic-gate * original signal mask ourself. 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 4447c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4457c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 4467c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 4477c478bd9Sstevel@tonic-gate } \ 4487c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4497c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 4507c478bd9Sstevel@tonic-gate restore_signals(self); \ 4517c478bd9Sstevel@tonic-gate } \ 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* 455f841f6adSraf * Cancellation prologue and epilogue functions, 456f841f6adSraf * for cancellation points too complex to include here. 45734709573Sraf */ 45834709573Sraf void 45934709573Sraf _cancel_prologue(void) 46034709573Sraf { 46134709573Sraf ulwp_t *self = curthread; 46234709573Sraf 463a574db85Sraf self->ul_cancel_prologue = 464a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | 465a574db85Sraf self->ul_critical | self->ul_sigdefer) != 0; 46634709573Sraf if (self->ul_cancel_prologue == 0) { 46734709573Sraf self->ul_save_async = self->ul_cancel_async; 46834709573Sraf if (!self->ul_cancel_disabled) { 46934709573Sraf self->ul_cancel_async = 1; 47034709573Sraf if (self->ul_cancel_pending) 4717257d1b4Sraf pthread_exit(PTHREAD_CANCELED); 47234709573Sraf } 47334709573Sraf self->ul_sp = stkptr(); 474a574db85Sraf } else if (self->ul_cancel_pending && 475a574db85Sraf !self->ul_cancel_disabled) { 476a574db85Sraf set_cancel_eintr_flag(self); 47734709573Sraf } 47834709573Sraf } 47934709573Sraf 48034709573Sraf void 48134709573Sraf _cancel_epilogue(void) 48234709573Sraf { 48334709573Sraf ulwp_t *self = curthread; 48434709573Sraf 48534709573Sraf if (self->ul_cancel_prologue == 0) { 48634709573Sraf self->ul_sp = 0; 48734709573Sraf self->ul_cancel_async = self->ul_save_async; 48834709573Sraf } 48934709573Sraf } 49034709573Sraf 49134709573Sraf /* 4927c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate int 4957c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 4967c478bd9Sstevel@tonic-gate { 4977c478bd9Sstevel@tonic-gate int error; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate PROLOGUE 500a574db85Sraf if (abort) 501a574db85Sraf return (EINTR); 502a574db85Sraf while ((error = __lwp_wait(tid, found)) == EINTR && !cancel_active()) 503a574db85Sraf continue; 5047c478bd9Sstevel@tonic-gate EPILOGUE 5057c478bd9Sstevel@tonic-gate return (error); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate ssize_t 5097257d1b4Sraf read(int fd, void *buf, size_t size) 5107c478bd9Sstevel@tonic-gate { 511a574db85Sraf extern ssize_t __read(int, void *, size_t); 5127c478bd9Sstevel@tonic-gate ssize_t rv; 5137c478bd9Sstevel@tonic-gate 514a574db85Sraf PERFORM(__read(fd, buf, size)) 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate ssize_t 5187257d1b4Sraf write(int fd, const void *buf, size_t size) 5197c478bd9Sstevel@tonic-gate { 520a574db85Sraf extern ssize_t __write(int, const void *, size_t); 5217c478bd9Sstevel@tonic-gate ssize_t rv; 5227c478bd9Sstevel@tonic-gate 523a574db85Sraf PERFORM(__write(fd, buf, size)) 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate int 5277257d1b4Sraf getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5287c478bd9Sstevel@tonic-gate int *flagsp) 5297c478bd9Sstevel@tonic-gate { 530a574db85Sraf extern int __getmsg(int, struct strbuf *, struct strbuf *, int *); 5317c478bd9Sstevel@tonic-gate int rv; 5327c478bd9Sstevel@tonic-gate 533a574db85Sraf PERFORM(__getmsg(fd, ctlptr, dataptr, flagsp)) 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate int 5377257d1b4Sraf getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5387c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 5397c478bd9Sstevel@tonic-gate { 540a574db85Sraf extern int __getpmsg(int, struct strbuf *, struct strbuf *, 5417c478bd9Sstevel@tonic-gate int *, int *); 5427c478bd9Sstevel@tonic-gate int rv; 5437c478bd9Sstevel@tonic-gate 544a574db85Sraf PERFORM(__getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate int 5487257d1b4Sraf putmsg(int fd, const struct strbuf *ctlptr, 5497c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5507c478bd9Sstevel@tonic-gate { 551a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5527c478bd9Sstevel@tonic-gate const struct strbuf *, int); 5537c478bd9Sstevel@tonic-gate int rv; 5547c478bd9Sstevel@tonic-gate 555a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags)) 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate int 5597c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 5607c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5617c478bd9Sstevel@tonic-gate { 562a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5637c478bd9Sstevel@tonic-gate const struct strbuf *, int); 5647c478bd9Sstevel@tonic-gate int rv; 5657c478bd9Sstevel@tonic-gate 566a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate int 5707257d1b4Sraf putpmsg(int fd, const struct strbuf *ctlptr, 5717c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5727c478bd9Sstevel@tonic-gate { 573a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5747c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 5757c478bd9Sstevel@tonic-gate int rv; 5767c478bd9Sstevel@tonic-gate 577a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags)) 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate int 5817c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 5827c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5837c478bd9Sstevel@tonic-gate { 584a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5857c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 5867c478bd9Sstevel@tonic-gate int rv; 5877c478bd9Sstevel@tonic-gate 588a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate int 5927257d1b4Sraf nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 5937c478bd9Sstevel@tonic-gate { 5947c478bd9Sstevel@tonic-gate int error; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate PROLOGUE 597a574db85Sraf error = abort? EINTR : __nanosleep(rqtp, rmtp); 5987c478bd9Sstevel@tonic-gate EPILOGUE 5997c478bd9Sstevel@tonic-gate if (error) { 6007c478bd9Sstevel@tonic-gate errno = error; 6017c478bd9Sstevel@tonic-gate return (-1); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate return (0); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate int 6077257d1b4Sraf clock_nanosleep(clockid_t clock_id, int flags, 6087c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 6097c478bd9Sstevel@tonic-gate { 6107c478bd9Sstevel@tonic-gate timespec_t reltime; 6117c478bd9Sstevel@tonic-gate hrtime_t start; 6127c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 6137c478bd9Sstevel@tonic-gate hrtime_t lapse; 6147c478bd9Sstevel@tonic-gate int error; 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate switch (clock_id) { 6177c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 6187c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 6197c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 6207c478bd9Sstevel@tonic-gate return (ENOTSUP); 6217c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 6227c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 6237c478bd9Sstevel@tonic-gate break; 6247c478bd9Sstevel@tonic-gate default: 6257c478bd9Sstevel@tonic-gate return (EINVAL); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6287c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6297c478bd9Sstevel@tonic-gate rmtp = NULL; 6307c478bd9Sstevel@tonic-gate } else { 6317c478bd9Sstevel@tonic-gate reltime = *rqtp; 6327c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 6337c478bd9Sstevel@tonic-gate start = gethrtime(); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate restart: 6367c478bd9Sstevel@tonic-gate PROLOGUE 637a574db85Sraf error = abort? EINTR : __nanosleep(&reltime, rmtp); 6387c478bd9Sstevel@tonic-gate EPILOGUE 6397c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 6407c478bd9Sstevel@tonic-gate /* 6417c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 6427c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 6437c478bd9Sstevel@tonic-gate * the system clock. 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6467c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6477c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 6487c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6497c478bd9Sstevel@tonic-gate goto restart; 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate } else { 6527c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6537c478bd9Sstevel@tonic-gate rqtp->tv_nsec; 6547c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 6557c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 6567c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 6577c478bd9Sstevel@tonic-gate goto restart; 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 6627c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 6637c478bd9Sstevel@tonic-gate /* 6647c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 6657c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 6667c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 6677c478bd9Sstevel@tonic-gate * 6687c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 6697c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 6707c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 6717c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 6727c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 6737c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6767c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 6777c478bd9Sstevel@tonic-gate goto restart; 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate return (error); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate unsigned int 6837257d1b4Sraf sleep(unsigned int sec) 6847c478bd9Sstevel@tonic-gate { 6857c478bd9Sstevel@tonic-gate unsigned int rem = 0; 6867c478bd9Sstevel@tonic-gate timespec_t ts; 6877c478bd9Sstevel@tonic-gate timespec_t tsr; 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 6907c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 6917257d1b4Sraf if (nanosleep(&ts, &tsr) == -1 && errno == EINTR) { 6927c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 6937c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 6947c478bd9Sstevel@tonic-gate rem++; 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate return (rem); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate int 7007257d1b4Sraf usleep(useconds_t usec) 7017c478bd9Sstevel@tonic-gate { 7027c478bd9Sstevel@tonic-gate timespec_t ts; 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 7057c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 7067257d1b4Sraf (void) nanosleep(&ts, NULL); 7077c478bd9Sstevel@tonic-gate return (0); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate int 7117257d1b4Sraf close(int fildes) 7127c478bd9Sstevel@tonic-gate { 713f841f6adSraf extern void _aio_close(int); 714a574db85Sraf extern int __close(int); 7157c478bd9Sstevel@tonic-gate int rv; 7167c478bd9Sstevel@tonic-gate 717720d4a35Sraf /* 718720d4a35Sraf * If we call _aio_close() while in a critical region, 719720d4a35Sraf * we will draw an ASSERT() failure, so don't do it. 720720d4a35Sraf * No calls to close() from within libc need _aio_close(); 721720d4a35Sraf * only the application's calls to close() need this, 722720d4a35Sraf * and such calls are never from a libc critical region. 723720d4a35Sraf */ 724720d4a35Sraf if (curthread->ul_critical == 0) 725f841f6adSraf _aio_close(fildes); 726a574db85Sraf PERFORM(__close(fildes)) 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate int 7307257d1b4Sraf creat(const char *path, mode_t mode) 7317c478bd9Sstevel@tonic-gate { 732a574db85Sraf extern int __creat(const char *, mode_t); 7337c478bd9Sstevel@tonic-gate int rv; 7347c478bd9Sstevel@tonic-gate 735a574db85Sraf PERFORM(__creat(path, mode)) 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7397c478bd9Sstevel@tonic-gate int 7407257d1b4Sraf creat64(const char *path, mode_t mode) 7417c478bd9Sstevel@tonic-gate { 742a574db85Sraf extern int __creat64(const char *, mode_t); 7437c478bd9Sstevel@tonic-gate int rv; 7447c478bd9Sstevel@tonic-gate 745a574db85Sraf PERFORM(__creat64(path, mode)) 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate int 7507257d1b4Sraf door_call(int d, door_arg_t *params) 7517c478bd9Sstevel@tonic-gate { 752a574db85Sraf extern int __door_call(int, door_arg_t *); 753a574db85Sraf int rv; 754a574db85Sraf 755a574db85Sraf PERFORM(__door_call(d, params)) 756a574db85Sraf } 757a574db85Sraf 758a574db85Sraf int 7597257d1b4Sraf fcntl(int fildes, int cmd, ...) 760a574db85Sraf { 761a574db85Sraf extern int __fcntl(int, int, ...); 7627c478bd9Sstevel@tonic-gate intptr_t arg; 7637c478bd9Sstevel@tonic-gate int rv; 7647c478bd9Sstevel@tonic-gate va_list ap; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate va_start(ap, cmd); 7677c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 7687c478bd9Sstevel@tonic-gate va_end(ap); 7697c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 770a574db85Sraf return (__fcntl(fildes, cmd, arg)); 771a574db85Sraf PERFORM(__fcntl(fildes, cmd, arg)) 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate int 7757257d1b4Sraf fdatasync(int fildes) 7761f8cf95fSraf { 777a574db85Sraf extern int __fdsync(int, int); 7781f8cf95fSraf int rv; 7791f8cf95fSraf 780a574db85Sraf PERFORM(__fdsync(fildes, FDSYNC)) 7811f8cf95fSraf } 7821f8cf95fSraf 7831f8cf95fSraf int 7847257d1b4Sraf fsync(int fildes) 7857c478bd9Sstevel@tonic-gate { 786a574db85Sraf extern int __fdsync(int, int); 7877c478bd9Sstevel@tonic-gate int rv; 7887c478bd9Sstevel@tonic-gate 789a574db85Sraf PERFORM(__fdsync(fildes, FSYNC)) 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate int 7937257d1b4Sraf lockf(int fildes, int function, off_t size) 7947c478bd9Sstevel@tonic-gate { 795a574db85Sraf extern int __lockf(int, int, off_t); 7967c478bd9Sstevel@tonic-gate int rv; 7977c478bd9Sstevel@tonic-gate 798a574db85Sraf PERFORM(__lockf(fildes, function, size)) 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate #if !defined(_LP64) 8027c478bd9Sstevel@tonic-gate int 8037257d1b4Sraf lockf64(int fildes, int function, off64_t size) 8047c478bd9Sstevel@tonic-gate { 805a574db85Sraf extern int __lockf64(int, int, off64_t); 8067c478bd9Sstevel@tonic-gate int rv; 8077c478bd9Sstevel@tonic-gate 808a574db85Sraf PERFORM(__lockf64(fildes, function, size)) 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate ssize_t 8137257d1b4Sraf msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 8147c478bd9Sstevel@tonic-gate { 815a574db85Sraf extern ssize_t __msgrcv(int, void *, size_t, long, int); 8167c478bd9Sstevel@tonic-gate ssize_t rv; 8177c478bd9Sstevel@tonic-gate 818a574db85Sraf PERFORM(__msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate int 8227257d1b4Sraf msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 8237c478bd9Sstevel@tonic-gate { 824a574db85Sraf extern int __msgsnd(int, const void *, size_t, int); 8257c478bd9Sstevel@tonic-gate int rv; 8267c478bd9Sstevel@tonic-gate 827a574db85Sraf PERFORM(__msgsnd(msqid, msgp, msgsz, msgflg)) 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate int 8317257d1b4Sraf msync(caddr_t addr, size_t len, int flags) 8327c478bd9Sstevel@tonic-gate { 833a574db85Sraf extern int __msync(caddr_t, size_t, int); 8347c478bd9Sstevel@tonic-gate int rv; 8357c478bd9Sstevel@tonic-gate 836a574db85Sraf PERFORM(__msync(addr, len, flags)) 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate int 8407257d1b4Sraf open(const char *path, int oflag, ...) 8417c478bd9Sstevel@tonic-gate { 842a574db85Sraf extern int __open(const char *, int, ...); 8437c478bd9Sstevel@tonic-gate mode_t mode; 8447c478bd9Sstevel@tonic-gate int rv; 8457c478bd9Sstevel@tonic-gate va_list ap; 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8487c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8497c478bd9Sstevel@tonic-gate va_end(ap); 850a574db85Sraf PERFORM(__open(path, oflag, mode)) 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate int 8547257d1b4Sraf openat(int fd, const char *path, int oflag, ...) 8557c478bd9Sstevel@tonic-gate { 856a574db85Sraf extern int __openat(int, const char *, int, ...); 8577c478bd9Sstevel@tonic-gate mode_t mode; 8587c478bd9Sstevel@tonic-gate int rv; 8597c478bd9Sstevel@tonic-gate va_list ap; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8627c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8637c478bd9Sstevel@tonic-gate va_end(ap); 864a574db85Sraf PERFORM(__openat(fd, path, oflag, mode)) 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate #if !defined(_LP64) 868a574db85Sraf int 8697257d1b4Sraf open64(const char *path, int oflag, ...) 8707c478bd9Sstevel@tonic-gate { 871a574db85Sraf extern int __open64(const char *, int, ...); 872a574db85Sraf mode_t mode; 873a574db85Sraf int rv; 874a574db85Sraf va_list ap; 8757c478bd9Sstevel@tonic-gate 876a574db85Sraf va_start(ap, oflag); 877a574db85Sraf mode = va_arg(ap, mode_t); 878a574db85Sraf va_end(ap); 879a574db85Sraf PERFORM(__open64(path, oflag, mode)) 880a574db85Sraf } 881a574db85Sraf 882a574db85Sraf int 8837257d1b4Sraf openat64(int fd, const char *path, int oflag, ...) 884a574db85Sraf { 885a574db85Sraf extern int __openat64(int, const char *, int, ...); 886a574db85Sraf mode_t mode; 887a574db85Sraf int rv; 888a574db85Sraf va_list ap; 889a574db85Sraf 890a574db85Sraf va_start(ap, oflag); 891a574db85Sraf mode = va_arg(ap, mode_t); 892a574db85Sraf va_end(ap); 893a574db85Sraf PERFORM(__openat64(fd, path, oflag, mode)) 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8967c478bd9Sstevel@tonic-gate 897a574db85Sraf int 8987257d1b4Sraf pause(void) 8997c478bd9Sstevel@tonic-gate { 900a574db85Sraf extern int __pause(void); 901a574db85Sraf int rv; 902a574db85Sraf 903a574db85Sraf PERFORM(__pause()) 904a574db85Sraf } 905a574db85Sraf 906a574db85Sraf ssize_t 9077257d1b4Sraf pread(int fildes, void *buf, size_t nbyte, off_t offset) 908a574db85Sraf { 909a574db85Sraf extern ssize_t __pread(int, void *, size_t, off_t); 9107c478bd9Sstevel@tonic-gate ssize_t rv; 9117c478bd9Sstevel@tonic-gate 912a574db85Sraf PERFORM(__pread(fildes, buf, nbyte, offset)) 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate #if !defined(_LP64) 9167c478bd9Sstevel@tonic-gate ssize_t 9177257d1b4Sraf pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 9187c478bd9Sstevel@tonic-gate { 919a574db85Sraf extern ssize_t __pread64(int, void *, size_t, off64_t); 9207c478bd9Sstevel@tonic-gate ssize_t rv; 9217c478bd9Sstevel@tonic-gate 922a574db85Sraf PERFORM(__pread64(fildes, buf, nbyte, offset)) 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate ssize_t 9277257d1b4Sraf pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 9287c478bd9Sstevel@tonic-gate { 929a574db85Sraf extern ssize_t __pwrite(int, const void *, size_t, off_t); 9307c478bd9Sstevel@tonic-gate ssize_t rv; 9317c478bd9Sstevel@tonic-gate 932a574db85Sraf PERFORM(__pwrite(fildes, buf, nbyte, offset)) 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 935a574db85Sraf #if !defined(_LP64) 936a574db85Sraf ssize_t 9377257d1b4Sraf pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 9387c478bd9Sstevel@tonic-gate { 939a574db85Sraf extern ssize_t __pwrite64(int, const void *, size_t, off64_t); 940a574db85Sraf ssize_t rv; 941a574db85Sraf 942a574db85Sraf PERFORM(__pwrite64(fildes, buf, nbyte, offset)) 943a574db85Sraf } 944a574db85Sraf #endif /* !_LP64 */ 945a574db85Sraf 946a574db85Sraf ssize_t 9477257d1b4Sraf readv(int fildes, const struct iovec *iov, int iovcnt) 948a574db85Sraf { 949a574db85Sraf extern ssize_t __readv(int, const struct iovec *, int); 950a574db85Sraf ssize_t rv; 951a574db85Sraf 952a574db85Sraf PERFORM(__readv(fildes, iov, iovcnt)) 953a574db85Sraf } 954a574db85Sraf 955a574db85Sraf int 9567257d1b4Sraf sigpause(int sig) 957a574db85Sraf { 958a574db85Sraf extern int __sigpause(int); 9597c478bd9Sstevel@tonic-gate int rv; 9607c478bd9Sstevel@tonic-gate 961a574db85Sraf PERFORM(__sigpause(sig)) 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate int 9657257d1b4Sraf sigsuspend(const sigset_t *set) 9667c478bd9Sstevel@tonic-gate { 9677c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 9687c478bd9Sstevel@tonic-gate int rv; 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 9717c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 9727c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9737c478bd9Sstevel@tonic-gate return (rv); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate int 9777c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 9787c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 9797c478bd9Sstevel@tonic-gate { 9807c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 9817c478bd9Sstevel@tonic-gate const sigset_t *); 9827c478bd9Sstevel@tonic-gate int rv; 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 9857c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 9867c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9877c478bd9Sstevel@tonic-gate return (rv); 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate int 9917257d1b4Sraf sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout) 9927c478bd9Sstevel@tonic-gate { 993f841f6adSraf extern int __sigtimedwait(const sigset_t *, siginfo_t *, 9947c478bd9Sstevel@tonic-gate const timespec_t *); 9957c478bd9Sstevel@tonic-gate siginfo_t info; 9967c478bd9Sstevel@tonic-gate int sig; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate PROLOGUE 999a574db85Sraf if (abort) { 1000a574db85Sraf *self->ul_errnop = EINTR; 1001a574db85Sraf sig = -1; 1002a574db85Sraf } else { 1003f841f6adSraf sig = __sigtimedwait(set, &info, timeout); 10047c478bd9Sstevel@tonic-gate if (sig == SIGCANCEL && 10057c478bd9Sstevel@tonic-gate (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 10067c478bd9Sstevel@tonic-gate do_sigcancel(); 1007a574db85Sraf *self->ul_errnop = EINTR; 10087c478bd9Sstevel@tonic-gate sig = -1; 10097c478bd9Sstevel@tonic-gate } 1010a574db85Sraf } 10117c478bd9Sstevel@tonic-gate EPILOGUE 10127c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 10138cd45542Sraf (void) memcpy(infop, &info, sizeof (*infop)); 10147c478bd9Sstevel@tonic-gate return (sig); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate int 10187257d1b4Sraf sigwait(sigset_t *set) 10197c478bd9Sstevel@tonic-gate { 10207257d1b4Sraf return (sigtimedwait(set, NULL, NULL)); 1021f841f6adSraf } 1022f841f6adSraf 1023f841f6adSraf int 10247257d1b4Sraf sigwaitinfo(const sigset_t *set, siginfo_t *info) 1025f841f6adSraf { 10267257d1b4Sraf return (sigtimedwait(set, info, NULL)); 1027f841f6adSraf } 1028f841f6adSraf 1029f841f6adSraf int 10307257d1b4Sraf sigqueue(pid_t pid, int signo, const union sigval value) 1031f841f6adSraf { 1032f841f6adSraf extern int __sigqueue(pid_t pid, int signo, 1033f841f6adSraf /* const union sigval */ void *value, int si_code, int block); 1034f841f6adSraf return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0)); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate int 1038a574db85Sraf _so_accept(int sock, struct sockaddr *addr, uint_t *addrlen, int version) 10397c478bd9Sstevel@tonic-gate { 1040a574db85Sraf extern int __so_accept(int, struct sockaddr *, uint_t *, int); 10417c478bd9Sstevel@tonic-gate int rv; 10427c478bd9Sstevel@tonic-gate 1043a574db85Sraf PERFORM(__so_accept(sock, addr, addrlen, version)) 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate int 1047a574db85Sraf _so_connect(int sock, struct sockaddr *addr, uint_t addrlen, int version) 10487c478bd9Sstevel@tonic-gate { 1049a574db85Sraf extern int __so_connect(int, struct sockaddr *, uint_t, int); 10507c478bd9Sstevel@tonic-gate int rv; 10517c478bd9Sstevel@tonic-gate 1052a574db85Sraf PERFORM(__so_connect(sock, addr, addrlen, version)) 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate 1055a574db85Sraf int 1056a574db85Sraf _so_recv(int sock, void *buf, size_t len, int flags) 10577c478bd9Sstevel@tonic-gate { 1058a574db85Sraf extern int __so_recv(int, void *, size_t, int); 1059a574db85Sraf int rv; 10607c478bd9Sstevel@tonic-gate 1061a574db85Sraf PERFORM(__so_recv(sock, buf, len, flags)) 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 1064a574db85Sraf int 1065a574db85Sraf _so_recvfrom(int sock, void *buf, size_t len, int flags, 1066a574db85Sraf struct sockaddr *addr, int *addrlen) 1067a574db85Sraf { 1068a574db85Sraf extern int __so_recvfrom(int, void *, size_t, int, 1069a574db85Sraf struct sockaddr *, int *); 1070a574db85Sraf int rv; 1071a574db85Sraf 1072a574db85Sraf PERFORM(__so_recvfrom(sock, buf, len, flags, addr, addrlen)) 1073a574db85Sraf } 1074a574db85Sraf 1075a574db85Sraf int 1076a574db85Sraf _so_recvmsg(int sock, struct msghdr *msg, int flags) 1077a574db85Sraf { 1078a574db85Sraf extern int __so_recvmsg(int, struct msghdr *, int); 1079a574db85Sraf int rv; 1080a574db85Sraf 1081a574db85Sraf PERFORM(__so_recvmsg(sock, msg, flags)) 1082a574db85Sraf } 1083a574db85Sraf 1084a574db85Sraf int 1085a574db85Sraf _so_send(int sock, const void *buf, size_t len, int flags) 1086a574db85Sraf { 1087a574db85Sraf extern int __so_send(int, const void *, size_t, int); 1088a574db85Sraf int rv; 1089a574db85Sraf 1090a574db85Sraf PERFORM(__so_send(sock, buf, len, flags)) 1091a574db85Sraf } 1092a574db85Sraf 1093a574db85Sraf int 1094a574db85Sraf _so_sendmsg(int sock, const struct msghdr *msg, int flags) 1095a574db85Sraf { 1096a574db85Sraf extern int __so_sendmsg(int, const struct msghdr *, int); 1097a574db85Sraf int rv; 1098a574db85Sraf 1099a574db85Sraf PERFORM(__so_sendmsg(sock, msg, flags)) 1100a574db85Sraf } 1101a574db85Sraf 1102a574db85Sraf int 1103a574db85Sraf _so_sendto(int sock, const void *buf, size_t len, int flags, 1104a574db85Sraf const struct sockaddr *addr, int *addrlen) 1105a574db85Sraf { 1106a574db85Sraf extern int __so_sendto(int, const void *, size_t, int, 1107a574db85Sraf const struct sockaddr *, int *); 1108a574db85Sraf int rv; 1109a574db85Sraf 1110a574db85Sraf PERFORM(__so_sendto(sock, buf, len, flags, addr, addrlen)) 1111a574db85Sraf } 1112a574db85Sraf 1113a574db85Sraf int 11147257d1b4Sraf tcdrain(int fildes) 1115a574db85Sraf { 1116a574db85Sraf extern int __tcdrain(int); 1117a574db85Sraf int rv; 1118a574db85Sraf 1119a574db85Sraf PERFORM(__tcdrain(fildes)) 1120a574db85Sraf } 1121a574db85Sraf 1122a574db85Sraf int 11237257d1b4Sraf waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 1124a574db85Sraf { 1125a574db85Sraf extern int __waitid(idtype_t, id_t, siginfo_t *, int); 1126a574db85Sraf int rv; 1127a574db85Sraf 1128a574db85Sraf if (options & WNOHANG) 1129a574db85Sraf return (__waitid(idtype, id, infop, options)); 1130a574db85Sraf PERFORM(__waitid(idtype, id, infop, options)) 1131a574db85Sraf } 1132a574db85Sraf 11337c478bd9Sstevel@tonic-gate ssize_t 11347257d1b4Sraf writev(int fildes, const struct iovec *iov, int iovcnt) 11357c478bd9Sstevel@tonic-gate { 1136a574db85Sraf extern ssize_t __writev(int, const struct iovec *, int); 11377c478bd9Sstevel@tonic-gate ssize_t rv; 11387c478bd9Sstevel@tonic-gate 1139a574db85Sraf PERFORM(__writev(fildes, iov, iovcnt)) 11407c478bd9Sstevel@tonic-gate } 1141