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. 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 397257d1b4Sraf /* 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 79d56c62ccSraf /* 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 857c478bd9Sstevel@tonic-gate /* 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 } 126b6233ca5Sraf 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 } 1397c478bd9Sstevel@tonic-gate 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 147dfb96a4fSab 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) 2083771f298SRoger A. Faulkner _prefork_handler(); 2097c478bd9Sstevel@tonic-gate 2102e145884Sraf /* 2112e145884Sraf * Block every other thread attempting thr_suspend() or thr_continue(). 2122e145884Sraf */ 2138cd45542Sraf (void) mutex_lock(&udp->fork_lock); 2142e145884Sraf 2157c478bd9Sstevel@tonic-gate /* 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 */ 246c242ec1bSRoger 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) 2513771f298SRoger A. Faulkner _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) 2583771f298SRoger A. Faulkner _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 */ 284dfb96a4fSab 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(); 324c242ec1bSRoger 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); \ 416*bdf0047cSRoger A. Faulkner self->ul_tmpmask = *sigmask; \ 4177c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 4187c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 4197c478bd9Sstevel@tonic-gate } \ 4207c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4217c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 4227c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 4237c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 4247c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 4257c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4267c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 4277c478bd9Sstevel@tonic-gate restore_signals(self); \ 4287c478bd9Sstevel@tonic-gate } \ 4297257d1b4Sraf pthread_exit(PTHREAD_CANCELED); \ 4307c478bd9Sstevel@tonic-gate } \ 4317c478bd9Sstevel@tonic-gate } \ 4327c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 4337c478bd9Sstevel@tonic-gate } \ 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 4387c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 4397c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 4407c478bd9Sstevel@tonic-gate * original signal mask ourself. 4417c478bd9Sstevel@tonic-gate */ 4427c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 4437c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4447c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 4457c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 4467c478bd9Sstevel@tonic-gate } \ 4477c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4487c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 4497c478bd9Sstevel@tonic-gate restore_signals(self); \ 4507c478bd9Sstevel@tonic-gate } \ 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 45334709573Sraf /* 454f841f6adSraf * Cancellation prologue and epilogue functions, 455f841f6adSraf * for cancellation points too complex to include here. 45634709573Sraf */ 45734709573Sraf void 45834709573Sraf _cancel_prologue(void) 45934709573Sraf { 46034709573Sraf ulwp_t *self = curthread; 46134709573Sraf 462a574db85Sraf self->ul_cancel_prologue = 463a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | 464a574db85Sraf self->ul_critical | self->ul_sigdefer) != 0; 46534709573Sraf if (self->ul_cancel_prologue == 0) { 46634709573Sraf self->ul_save_async = self->ul_cancel_async; 46734709573Sraf if (!self->ul_cancel_disabled) { 46834709573Sraf self->ul_cancel_async = 1; 46934709573Sraf if (self->ul_cancel_pending) 4707257d1b4Sraf pthread_exit(PTHREAD_CANCELED); 47134709573Sraf } 47234709573Sraf self->ul_sp = stkptr(); 473a574db85Sraf } else if (self->ul_cancel_pending && 474a574db85Sraf !self->ul_cancel_disabled) { 475a574db85Sraf set_cancel_eintr_flag(self); 47634709573Sraf } 47734709573Sraf } 47834709573Sraf 47934709573Sraf void 48034709573Sraf _cancel_epilogue(void) 48134709573Sraf { 48234709573Sraf ulwp_t *self = curthread; 48334709573Sraf 48434709573Sraf if (self->ul_cancel_prologue == 0) { 48534709573Sraf self->ul_sp = 0; 48634709573Sraf self->ul_cancel_async = self->ul_save_async; 48734709573Sraf } 48834709573Sraf } 48934709573Sraf 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate int 4947c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate int error; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate PROLOGUE 499a574db85Sraf if (abort) 500a574db85Sraf return (EINTR); 501a574db85Sraf while ((error = __lwp_wait(tid, found)) == EINTR && !cancel_active()) 502a574db85Sraf continue; 5037c478bd9Sstevel@tonic-gate EPILOGUE 5047c478bd9Sstevel@tonic-gate return (error); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate ssize_t 5087257d1b4Sraf read(int fd, void *buf, size_t size) 5097c478bd9Sstevel@tonic-gate { 510a574db85Sraf extern ssize_t __read(int, void *, size_t); 5117c478bd9Sstevel@tonic-gate ssize_t rv; 5127c478bd9Sstevel@tonic-gate 513a574db85Sraf PERFORM(__read(fd, buf, size)) 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate ssize_t 5177257d1b4Sraf write(int fd, const void *buf, size_t size) 5187c478bd9Sstevel@tonic-gate { 519a574db85Sraf extern ssize_t __write(int, const void *, size_t); 5207c478bd9Sstevel@tonic-gate ssize_t rv; 5217c478bd9Sstevel@tonic-gate 522a574db85Sraf PERFORM(__write(fd, buf, size)) 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate int 5267257d1b4Sraf getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5277c478bd9Sstevel@tonic-gate int *flagsp) 5287c478bd9Sstevel@tonic-gate { 529a574db85Sraf extern int __getmsg(int, struct strbuf *, struct strbuf *, int *); 5307c478bd9Sstevel@tonic-gate int rv; 5317c478bd9Sstevel@tonic-gate 532a574db85Sraf PERFORM(__getmsg(fd, ctlptr, dataptr, flagsp)) 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate int 5367257d1b4Sraf getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5377c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 5387c478bd9Sstevel@tonic-gate { 539a574db85Sraf extern int __getpmsg(int, struct strbuf *, struct strbuf *, 5402e145884Sraf int *, int *); 5417c478bd9Sstevel@tonic-gate int rv; 5427c478bd9Sstevel@tonic-gate 543a574db85Sraf PERFORM(__getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate int 5477257d1b4Sraf putmsg(int fd, const struct strbuf *ctlptr, 5487c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5497c478bd9Sstevel@tonic-gate { 550a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5512e145884Sraf const struct strbuf *, int); 5527c478bd9Sstevel@tonic-gate int rv; 5537c478bd9Sstevel@tonic-gate 554a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags)) 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate int 5587c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 5597c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5607c478bd9Sstevel@tonic-gate { 561a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5622e145884Sraf const struct strbuf *, int); 5637c478bd9Sstevel@tonic-gate int rv; 5647c478bd9Sstevel@tonic-gate 565a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate int 5697257d1b4Sraf putpmsg(int fd, const struct strbuf *ctlptr, 5707c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5717c478bd9Sstevel@tonic-gate { 572a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5732e145884Sraf const struct strbuf *, int, int); 5747c478bd9Sstevel@tonic-gate int rv; 5757c478bd9Sstevel@tonic-gate 576a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags)) 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate int 5807c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 5817c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5827c478bd9Sstevel@tonic-gate { 583a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5842e145884Sraf const struct strbuf *, int, int); 5857c478bd9Sstevel@tonic-gate int rv; 5867c478bd9Sstevel@tonic-gate 587a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate int 5917257d1b4Sraf nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 5927c478bd9Sstevel@tonic-gate { 5937c478bd9Sstevel@tonic-gate int error; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate PROLOGUE 596a574db85Sraf error = abort? EINTR : __nanosleep(rqtp, rmtp); 5977c478bd9Sstevel@tonic-gate EPILOGUE 5987c478bd9Sstevel@tonic-gate if (error) { 5997c478bd9Sstevel@tonic-gate errno = error; 6007c478bd9Sstevel@tonic-gate return (-1); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate return (0); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate int 6067257d1b4Sraf clock_nanosleep(clockid_t clock_id, int flags, 6077c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 6087c478bd9Sstevel@tonic-gate { 6097c478bd9Sstevel@tonic-gate timespec_t reltime; 6107c478bd9Sstevel@tonic-gate hrtime_t start; 6117c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 6127c478bd9Sstevel@tonic-gate hrtime_t lapse; 6137c478bd9Sstevel@tonic-gate int error; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate switch (clock_id) { 6167c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 6177c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 6187c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 6197c478bd9Sstevel@tonic-gate return (ENOTSUP); 6207c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 6217c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 6227c478bd9Sstevel@tonic-gate break; 6237c478bd9Sstevel@tonic-gate default: 6247c478bd9Sstevel@tonic-gate return (EINVAL); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6277c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6287c478bd9Sstevel@tonic-gate rmtp = NULL; 6297c478bd9Sstevel@tonic-gate } else { 6307c478bd9Sstevel@tonic-gate reltime = *rqtp; 6317c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 6327c478bd9Sstevel@tonic-gate start = gethrtime(); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate restart: 6357c478bd9Sstevel@tonic-gate PROLOGUE 636a574db85Sraf error = abort? EINTR : __nanosleep(&reltime, rmtp); 6377c478bd9Sstevel@tonic-gate EPILOGUE 6387c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 6397c478bd9Sstevel@tonic-gate /* 6407c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 6417c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 6427c478bd9Sstevel@tonic-gate * the system clock. 6437c478bd9Sstevel@tonic-gate */ 6447c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6457c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6467c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 6477c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6487c478bd9Sstevel@tonic-gate goto restart; 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate } else { 6517c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6522e145884Sraf rqtp->tv_nsec; 6537c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 6547c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 6557c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 6567c478bd9Sstevel@tonic-gate goto restart; 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 6617c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 6647c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 6657c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 6667c478bd9Sstevel@tonic-gate * 6677c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 6687c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 6697c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 6707c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 6717c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 6727c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6757c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 6767c478bd9Sstevel@tonic-gate goto restart; 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate return (error); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate unsigned int 6827257d1b4Sraf sleep(unsigned int sec) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate unsigned int rem = 0; 6857c478bd9Sstevel@tonic-gate timespec_t ts; 6867c478bd9Sstevel@tonic-gate timespec_t tsr; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 6897c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 6907257d1b4Sraf if (nanosleep(&ts, &tsr) == -1 && errno == EINTR) { 6917c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 6927c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 6937c478bd9Sstevel@tonic-gate rem++; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate return (rem); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate int 6997257d1b4Sraf usleep(useconds_t usec) 7007c478bd9Sstevel@tonic-gate { 7017c478bd9Sstevel@tonic-gate timespec_t ts; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 7047c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 7057257d1b4Sraf (void) nanosleep(&ts, NULL); 7067c478bd9Sstevel@tonic-gate return (0); 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate int 7107257d1b4Sraf close(int fildes) 7117c478bd9Sstevel@tonic-gate { 712f841f6adSraf extern void _aio_close(int); 713a574db85Sraf extern int __close(int); 7147c478bd9Sstevel@tonic-gate int rv; 7157c478bd9Sstevel@tonic-gate 716720d4a35Sraf /* 717720d4a35Sraf * If we call _aio_close() while in a critical region, 718720d4a35Sraf * we will draw an ASSERT() failure, so don't do it. 719720d4a35Sraf * No calls to close() from within libc need _aio_close(); 720720d4a35Sraf * only the application's calls to close() need this, 721720d4a35Sraf * and such calls are never from a libc critical region. 722720d4a35Sraf */ 723720d4a35Sraf if (curthread->ul_critical == 0) 724720d4a35Sraf _aio_close(fildes); 725a574db85Sraf PERFORM(__close(fildes)) 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 728a574db85Sraf int 7297257d1b4Sraf door_call(int d, door_arg_t *params) 730a574db85Sraf { 731a574db85Sraf extern int __door_call(int, door_arg_t *); 732a574db85Sraf int rv; 733a574db85Sraf 734a574db85Sraf PERFORM(__door_call(d, params)) 735a574db85Sraf } 736a574db85Sraf 7377c478bd9Sstevel@tonic-gate int 7387257d1b4Sraf fcntl(int fildes, int cmd, ...) 7397c478bd9Sstevel@tonic-gate { 740a574db85Sraf extern int __fcntl(int, int, ...); 7417c478bd9Sstevel@tonic-gate intptr_t arg; 7427c478bd9Sstevel@tonic-gate int rv; 7437c478bd9Sstevel@tonic-gate va_list ap; 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate va_start(ap, cmd); 7467c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 7477c478bd9Sstevel@tonic-gate va_end(ap); 7487c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 749a574db85Sraf return (__fcntl(fildes, cmd, arg)); 750a574db85Sraf PERFORM(__fcntl(fildes, cmd, arg)) 7517c478bd9Sstevel@tonic-gate } 7527c478bd9Sstevel@tonic-gate 7531f8cf95fSraf int 7547257d1b4Sraf fdatasync(int fildes) 7551f8cf95fSraf { 756a574db85Sraf extern int __fdsync(int, int); 7571f8cf95fSraf int rv; 7581f8cf95fSraf 759a574db85Sraf PERFORM(__fdsync(fildes, FDSYNC)) 7601f8cf95fSraf } 7611f8cf95fSraf 7627c478bd9Sstevel@tonic-gate int 7637257d1b4Sraf fsync(int fildes) 7647c478bd9Sstevel@tonic-gate { 765a574db85Sraf extern int __fdsync(int, int); 7667c478bd9Sstevel@tonic-gate int rv; 7677c478bd9Sstevel@tonic-gate 768a574db85Sraf PERFORM(__fdsync(fildes, FSYNC)) 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate int 7727257d1b4Sraf lockf(int fildes, int function, off_t size) 7737c478bd9Sstevel@tonic-gate { 774a574db85Sraf extern int __lockf(int, int, off_t); 7757c478bd9Sstevel@tonic-gate int rv; 7767c478bd9Sstevel@tonic-gate 777a574db85Sraf PERFORM(__lockf(fildes, function, size)) 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7817c478bd9Sstevel@tonic-gate int 7827257d1b4Sraf lockf64(int fildes, int function, off64_t size) 7837c478bd9Sstevel@tonic-gate { 784a574db85Sraf extern int __lockf64(int, int, off64_t); 7857c478bd9Sstevel@tonic-gate int rv; 7867c478bd9Sstevel@tonic-gate 787a574db85Sraf PERFORM(__lockf64(fildes, function, size)) 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate ssize_t 7927257d1b4Sraf msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 7937c478bd9Sstevel@tonic-gate { 794a574db85Sraf extern ssize_t __msgrcv(int, void *, size_t, long, int); 7957c478bd9Sstevel@tonic-gate ssize_t rv; 7967c478bd9Sstevel@tonic-gate 797a574db85Sraf PERFORM(__msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 798a574db85Sraf } 799a574db85Sraf 800a574db85Sraf int 8017257d1b4Sraf msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 802a574db85Sraf { 803a574db85Sraf extern int __msgsnd(int, const void *, size_t, int); 804a574db85Sraf int rv; 805a574db85Sraf 806a574db85Sraf PERFORM(__msgsnd(msqid, msgp, msgsz, msgflg)) 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate int 8107257d1b4Sraf msync(caddr_t addr, size_t len, int flags) 8117c478bd9Sstevel@tonic-gate { 812a574db85Sraf extern int __msync(caddr_t, size_t, int); 8137c478bd9Sstevel@tonic-gate int rv; 8147c478bd9Sstevel@tonic-gate 815a574db85Sraf PERFORM(__msync(addr, len, flags)) 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate int 8198fd04b83SRoger A. Faulkner openat(int fd, const char *path, int oflag, ...) 8207c478bd9Sstevel@tonic-gate { 821a574db85Sraf mode_t mode; 8227c478bd9Sstevel@tonic-gate int rv; 823a574db85Sraf va_list ap; 8247c478bd9Sstevel@tonic-gate 825a574db85Sraf va_start(ap, oflag); 826a574db85Sraf mode = va_arg(ap, mode_t); 827a574db85Sraf va_end(ap); 8288fd04b83SRoger A. Faulkner PERFORM(__openat(fd, path, oflag, mode)) 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate int 8328fd04b83SRoger A. Faulkner open(const char *path, int oflag, ...) 8337c478bd9Sstevel@tonic-gate { 8347c478bd9Sstevel@tonic-gate mode_t mode; 8357c478bd9Sstevel@tonic-gate int rv; 8367c478bd9Sstevel@tonic-gate va_list ap; 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8397c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8407c478bd9Sstevel@tonic-gate va_end(ap); 8418fd04b83SRoger A. Faulkner PERFORM(__open(path, oflag, mode)) 8428fd04b83SRoger A. Faulkner } 8438fd04b83SRoger A. Faulkner 8448fd04b83SRoger A. Faulkner int 8458fd04b83SRoger A. Faulkner creat(const char *path, mode_t mode) 8468fd04b83SRoger A. Faulkner { 8478fd04b83SRoger A. Faulkner return (open(path, O_WRONLY | O_CREAT | O_TRUNC, mode)); 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate #if !defined(_LP64) 851a574db85Sraf int 8528fd04b83SRoger A. Faulkner openat64(int fd, const char *path, int oflag, ...) 853a574db85Sraf { 854a574db85Sraf mode_t mode; 855a574db85Sraf int rv; 856a574db85Sraf va_list ap; 857a574db85Sraf 858a574db85Sraf va_start(ap, oflag); 859a574db85Sraf mode = va_arg(ap, mode_t); 860a574db85Sraf va_end(ap); 8618fd04b83SRoger A. Faulkner PERFORM(__openat64(fd, path, oflag, mode)) 862a574db85Sraf } 863a574db85Sraf 8647c478bd9Sstevel@tonic-gate int 8658fd04b83SRoger A. Faulkner open64(const char *path, int oflag, ...) 8667c478bd9Sstevel@tonic-gate { 8677c478bd9Sstevel@tonic-gate mode_t mode; 8687c478bd9Sstevel@tonic-gate int rv; 8697c478bd9Sstevel@tonic-gate va_list ap; 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8727c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8737c478bd9Sstevel@tonic-gate va_end(ap); 8748fd04b83SRoger A. Faulkner PERFORM(__open64(path, oflag, mode)) 8758fd04b83SRoger A. Faulkner } 8768fd04b83SRoger A. Faulkner 8778fd04b83SRoger A. Faulkner int 8788fd04b83SRoger A. Faulkner creat64(const char *path, mode_t mode) 8798fd04b83SRoger A. Faulkner { 8808fd04b83SRoger A. Faulkner return (open64(path, O_WRONLY | O_CREAT | O_TRUNC, mode)); 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate int 8857257d1b4Sraf pause(void) 8867c478bd9Sstevel@tonic-gate { 887a574db85Sraf extern int __pause(void); 8887c478bd9Sstevel@tonic-gate int rv; 8897c478bd9Sstevel@tonic-gate 890a574db85Sraf PERFORM(__pause()) 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate ssize_t 8947257d1b4Sraf pread(int fildes, void *buf, size_t nbyte, off_t offset) 8957c478bd9Sstevel@tonic-gate { 896a574db85Sraf extern ssize_t __pread(int, void *, size_t, off_t); 8977c478bd9Sstevel@tonic-gate ssize_t rv; 8987c478bd9Sstevel@tonic-gate 899a574db85Sraf PERFORM(__pread(fildes, buf, nbyte, offset)) 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate #if !defined(_LP64) 9037c478bd9Sstevel@tonic-gate ssize_t 9047257d1b4Sraf pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 9057c478bd9Sstevel@tonic-gate { 906a574db85Sraf extern ssize_t __pread64(int, void *, size_t, off64_t); 9077c478bd9Sstevel@tonic-gate ssize_t rv; 9087c478bd9Sstevel@tonic-gate 909a574db85Sraf PERFORM(__pread64(fildes, buf, nbyte, offset)) 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate ssize_t 9147257d1b4Sraf pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 9157c478bd9Sstevel@tonic-gate { 916a574db85Sraf extern ssize_t __pwrite(int, const void *, size_t, off_t); 9177c478bd9Sstevel@tonic-gate ssize_t rv; 9187c478bd9Sstevel@tonic-gate 919a574db85Sraf PERFORM(__pwrite(fildes, buf, nbyte, offset)) 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate #if !defined(_LP64) 9237c478bd9Sstevel@tonic-gate ssize_t 9247257d1b4Sraf pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 9257c478bd9Sstevel@tonic-gate { 926a574db85Sraf extern ssize_t __pwrite64(int, const void *, size_t, off64_t); 9277c478bd9Sstevel@tonic-gate ssize_t rv; 9287c478bd9Sstevel@tonic-gate 929a574db85Sraf PERFORM(__pwrite64(fildes, buf, nbyte, offset)) 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate ssize_t 9347257d1b4Sraf readv(int fildes, const struct iovec *iov, int iovcnt) 9357c478bd9Sstevel@tonic-gate { 936a574db85Sraf extern ssize_t __readv(int, const struct iovec *, int); 9377c478bd9Sstevel@tonic-gate ssize_t rv; 9387c478bd9Sstevel@tonic-gate 939a574db85Sraf PERFORM(__readv(fildes, iov, iovcnt)) 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate int 9437257d1b4Sraf sigpause(int sig) 9447c478bd9Sstevel@tonic-gate { 945a574db85Sraf extern int __sigpause(int); 9467c478bd9Sstevel@tonic-gate int rv; 9477c478bd9Sstevel@tonic-gate 948a574db85Sraf PERFORM(__sigpause(sig)) 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate int 9527257d1b4Sraf sigsuspend(const sigset_t *set) 9537c478bd9Sstevel@tonic-gate { 9547c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 9557c478bd9Sstevel@tonic-gate int rv; 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 9587c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 9597c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9607c478bd9Sstevel@tonic-gate return (rv); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate int 9647c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 9657c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 9667c478bd9Sstevel@tonic-gate { 9677c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 9682e145884Sraf const sigset_t *); 9697c478bd9Sstevel@tonic-gate int rv; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 9727c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 9737c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9747c478bd9Sstevel@tonic-gate return (rv); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate int 9787257d1b4Sraf sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout) 9797c478bd9Sstevel@tonic-gate { 980f841f6adSraf extern int __sigtimedwait(const sigset_t *, siginfo_t *, 9812e145884Sraf const timespec_t *); 9827c478bd9Sstevel@tonic-gate siginfo_t info; 9837c478bd9Sstevel@tonic-gate int sig; 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate PROLOGUE 986a574db85Sraf if (abort) { 987a574db85Sraf *self->ul_errnop = EINTR; 9887c478bd9Sstevel@tonic-gate sig = -1; 989a574db85Sraf } else { 990a574db85Sraf sig = __sigtimedwait(set, &info, timeout); 991a574db85Sraf if (sig == SIGCANCEL && 992a574db85Sraf (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 993a574db85Sraf do_sigcancel(); 994a574db85Sraf *self->ul_errnop = EINTR; 995a574db85Sraf sig = -1; 996a574db85Sraf } 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate EPILOGUE 9997c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 10008cd45542Sraf (void) memcpy(infop, &info, sizeof (*infop)); 10017c478bd9Sstevel@tonic-gate return (sig); 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate int 10057257d1b4Sraf sigwait(sigset_t *set) 10067c478bd9Sstevel@tonic-gate { 10077257d1b4Sraf return (sigtimedwait(set, NULL, NULL)); 1008f841f6adSraf } 1009f841f6adSraf 1010f841f6adSraf int 10117257d1b4Sraf sigwaitinfo(const sigset_t *set, siginfo_t *info) 1012f841f6adSraf { 10137257d1b4Sraf return (sigtimedwait(set, info, NULL)); 1014f841f6adSraf } 1015f841f6adSraf 1016f841f6adSraf int 10177257d1b4Sraf sigqueue(pid_t pid, int signo, const union sigval value) 1018f841f6adSraf { 1019f841f6adSraf extern int __sigqueue(pid_t pid, int signo, 10202e145884Sraf /* const union sigval */ void *value, int si_code, int block); 1021f841f6adSraf return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0)); 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate int 1025a574db85Sraf _so_accept(int sock, struct sockaddr *addr, uint_t *addrlen, int version) 10267c478bd9Sstevel@tonic-gate { 1027a574db85Sraf extern int __so_accept(int, struct sockaddr *, uint_t *, int); 10287c478bd9Sstevel@tonic-gate int rv; 10297c478bd9Sstevel@tonic-gate 1030a574db85Sraf PERFORM(__so_accept(sock, addr, addrlen, version)) 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate 1033a574db85Sraf int 1034a574db85Sraf _so_connect(int sock, struct sockaddr *addr, uint_t addrlen, int version) 10357c478bd9Sstevel@tonic-gate { 1036a574db85Sraf extern int __so_connect(int, struct sockaddr *, uint_t, int); 1037a574db85Sraf int rv; 10387c478bd9Sstevel@tonic-gate 1039a574db85Sraf PERFORM(__so_connect(sock, addr, addrlen, version)) 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 1042a574db85Sraf int 1043a574db85Sraf _so_recv(int sock, void *buf, size_t len, int flags) 10447c478bd9Sstevel@tonic-gate { 1045a574db85Sraf extern int __so_recv(int, void *, size_t, int); 1046a574db85Sraf int rv; 10477c478bd9Sstevel@tonic-gate 1048a574db85Sraf PERFORM(__so_recv(sock, buf, len, flags)) 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate int 1052a574db85Sraf _so_recvfrom(int sock, void *buf, size_t len, int flags, 1053a574db85Sraf struct sockaddr *addr, int *addrlen) 10547c478bd9Sstevel@tonic-gate { 1055a574db85Sraf extern int __so_recvfrom(int, void *, size_t, int, 1056a574db85Sraf struct sockaddr *, int *); 10577c478bd9Sstevel@tonic-gate int rv; 10587c478bd9Sstevel@tonic-gate 1059a574db85Sraf PERFORM(__so_recvfrom(sock, buf, len, flags, addr, addrlen)) 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 1062a574db85Sraf int 1063a574db85Sraf _so_recvmsg(int sock, struct msghdr *msg, int flags) 1064a574db85Sraf { 1065a574db85Sraf extern int __so_recvmsg(int, struct msghdr *, int); 1066a574db85Sraf int rv; 1067a574db85Sraf 1068a574db85Sraf PERFORM(__so_recvmsg(sock, msg, flags)) 1069a574db85Sraf } 1070a574db85Sraf 1071a574db85Sraf int 1072a574db85Sraf _so_send(int sock, const void *buf, size_t len, int flags) 1073a574db85Sraf { 1074a574db85Sraf extern int __so_send(int, const void *, size_t, int); 1075a574db85Sraf int rv; 1076a574db85Sraf 1077a574db85Sraf PERFORM(__so_send(sock, buf, len, flags)) 1078a574db85Sraf } 1079a574db85Sraf 1080a574db85Sraf int 1081a574db85Sraf _so_sendmsg(int sock, const struct msghdr *msg, int flags) 10827c478bd9Sstevel@tonic-gate { 1083a574db85Sraf extern int __so_sendmsg(int, const struct msghdr *, int); 1084a574db85Sraf int rv; 1085a574db85Sraf 1086a574db85Sraf PERFORM(__so_sendmsg(sock, msg, flags)) 1087a574db85Sraf } 1088a574db85Sraf 1089a574db85Sraf int 1090a574db85Sraf _so_sendto(int sock, const void *buf, size_t len, int flags, 1091a574db85Sraf const struct sockaddr *addr, int *addrlen) 1092a574db85Sraf { 1093a574db85Sraf extern int __so_sendto(int, const void *, size_t, int, 1094a574db85Sraf const struct sockaddr *, int *); 1095a574db85Sraf int rv; 1096a574db85Sraf 1097a574db85Sraf PERFORM(__so_sendto(sock, buf, len, flags, addr, addrlen)) 1098a574db85Sraf } 1099a574db85Sraf 1100a574db85Sraf int 11017257d1b4Sraf tcdrain(int fildes) 1102a574db85Sraf { 1103a574db85Sraf extern int __tcdrain(int); 1104a574db85Sraf int rv; 1105a574db85Sraf 1106a574db85Sraf PERFORM(__tcdrain(fildes)) 1107a574db85Sraf } 1108a574db85Sraf 1109a574db85Sraf int 11107257d1b4Sraf waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 1111a574db85Sraf { 1112a574db85Sraf extern int __waitid(idtype_t, id_t, siginfo_t *, int); 1113a574db85Sraf int rv; 11147c478bd9Sstevel@tonic-gate 1115a574db85Sraf if (options & WNOHANG) 1116a574db85Sraf return (__waitid(idtype, id, infop, options)); 1117a574db85Sraf PERFORM(__waitid(idtype, id, infop, options)) 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate ssize_t 11217257d1b4Sraf writev(int fildes, const struct iovec *iov, int iovcnt) 11227c478bd9Sstevel@tonic-gate { 1123a574db85Sraf extern ssize_t __writev(int, const struct iovec *, int); 11247c478bd9Sstevel@tonic-gate ssize_t rv; 11257c478bd9Sstevel@tonic-gate 1126a574db85Sraf PERFORM(__writev(fildes, iov, iovcnt)) 11277c478bd9Sstevel@tonic-gate } 1128