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