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 /* 2336319254Sraf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include "lint.h" 307c478bd9Sstevel@tonic-gate #include "thr_uberdata.h" 317c478bd9Sstevel@tonic-gate #include <stdarg.h> 327c478bd9Sstevel@tonic-gate #include <poll.h> 337c478bd9Sstevel@tonic-gate #include <stropts.h> 347c478bd9Sstevel@tonic-gate #include <dlfcn.h> 357c478bd9Sstevel@tonic-gate #include <sys/uio.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* 38*2e145884Sraf * fork_lock_enter() does triple-duty. Not only does it (and atfork_lock) 39*2e145884Sraf * serialize calls to fork() and forkall(), but it also serializes calls to 40*2e145884Sraf * thr_suspend() and thr_continue() (fork() and forkall() also suspend other 41*2e145884Sraf * threads), and furthermore it serializes I18N calls to functions in other 427c478bd9Sstevel@tonic-gate * dlopen()ed L10N objects that might be calling malloc()/free(). 437c478bd9Sstevel@tonic-gate */ 44*2e145884Sraf void 45*2e145884Sraf fork_lock_enter(void) 467c478bd9Sstevel@tonic-gate { 477c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 50*2e145884Sraf (void) _private_mutex_lock(&self->ul_uberdata->fork_lock); 517c478bd9Sstevel@tonic-gate } 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate void 547c478bd9Sstevel@tonic-gate fork_lock_exit(void) 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 59*2e145884Sraf (void) _private_mutex_unlock(&self->ul_uberdata->fork_lock); 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate 62657b1f3dSraf #pragma weak forkx = _private_forkx 63657b1f3dSraf #pragma weak _forkx = _private_forkx 64dfb96a4fSab pid_t 65657b1f3dSraf _private_forkx(int flags) 667c478bd9Sstevel@tonic-gate { 677c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 687c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 697c478bd9Sstevel@tonic-gate pid_t pid; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 727c478bd9Sstevel@tonic-gate /* 737c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 747c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 757c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 767c478bd9Sstevel@tonic-gate * must never call fork(). 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 797c478bd9Sstevel@tonic-gate errno = ENOTSUP; 807c478bd9Sstevel@tonic-gate return (-1); 817c478bd9Sstevel@tonic-gate } 82657b1f3dSraf pid = __forkx(flags); 837c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 847c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 857c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate return (pid); 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate 90*2e145884Sraf sigoff(self); 91*2e145884Sraf if (self->ul_fork) { 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 947c478bd9Sstevel@tonic-gate */ 95*2e145884Sraf sigon(self); 96*2e145884Sraf errno = EDEADLK; 977c478bd9Sstevel@tonic-gate return (-1); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate self->ul_fork = 1; 100*2e145884Sraf (void) _private_mutex_lock(&udp->atfork_lock); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* 1037c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 1047c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 105*2e145884Sraf * internal lmutex_lock()-acquired locks while invoking them. 106*2e145884Sraf * We hold only udp->atfork_lock to protect the atfork linkages. 107*2e145884Sraf * If one of these pthread_atfork() functions attempts to fork 108*2e145884Sraf * or to call pthread_atfork(), it will detect the error and 109*2e145884Sraf * fail with EDEADLK. Otherwise, the pthread_atfork() functions 1107c478bd9Sstevel@tonic-gate * are free to do anything they please (except they will not 1117c478bd9Sstevel@tonic-gate * receive any signals). 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate _prefork_handler(); 1147c478bd9Sstevel@tonic-gate 115*2e145884Sraf /* 116*2e145884Sraf * Block every other thread attempting thr_suspend() or thr_continue(). 117*2e145884Sraf * This also blocks every other thread attempting calls to I18N 118*2e145884Sraf * functions in dlopen()ed L10N objects, but this is benign; 119*2e145884Sraf * the other threads will soon be suspended anyway. 120*2e145884Sraf */ 121*2e145884Sraf fork_lock_enter(); 122*2e145884Sraf 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Block all signals. 125*2e145884Sraf * Just deferring them via sigoff() is not enough. 1267c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 127657b1f3dSraf * that was actually sent to the parent before __forkx(). 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate block_all_signals(self); 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 1337c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 1347c478bd9Sstevel@tonic-gate * Thus, we are assured that no library locks are held 135657b1f3dSraf * while we invoke fork() from the current thread. 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate suspend_fork(); 1387c478bd9Sstevel@tonic-gate 139657b1f3dSraf pid = __forkx(flags); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 1447c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 145657b1f3dSraf * Because we blocked all signals before __forkx(), a 1467c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 1497c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 1507c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 1517c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 1527c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 1537c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 154883492d5Sraf unregister_locks(); 155f841f6adSraf postfork1_child(); 1567c478bd9Sstevel@tonic-gate restore_signals(self); 157*2e145884Sraf fork_lock_exit(); 1587c478bd9Sstevel@tonic-gate _postfork_child_handler(); 1597c478bd9Sstevel@tonic-gate } else { 160657b1f3dSraf /* restart all threads that were suspended for fork() */ 1617c478bd9Sstevel@tonic-gate continue_fork(0); 1627c478bd9Sstevel@tonic-gate restore_signals(self); 163*2e145884Sraf fork_lock_exit(); 1647c478bd9Sstevel@tonic-gate _postfork_parent_handler(); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 167*2e145884Sraf (void) _private_mutex_unlock(&udp->atfork_lock); 1687c478bd9Sstevel@tonic-gate self->ul_fork = 0; 169*2e145884Sraf sigon(self); 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate return (pid); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 175657b1f3dSraf * fork() is fork1() for both Posix threads and Solaris threads. 176657b1f3dSraf * The forkall() interface exists for applications that require 177657b1f3dSraf * the semantics of replicating all threads. 1787c478bd9Sstevel@tonic-gate */ 179657b1f3dSraf #pragma weak fork1 = _fork 180657b1f3dSraf #pragma weak _fork1 = _fork 181657b1f3dSraf #pragma weak fork = _fork 1827c478bd9Sstevel@tonic-gate pid_t 183657b1f3dSraf _fork(void) 184657b1f3dSraf { 185657b1f3dSraf return (_private_forkx(0)); 186657b1f3dSraf } 187657b1f3dSraf 188657b1f3dSraf /* 189657b1f3dSraf * Much of the logic here is the same as in forkx(). 190657b1f3dSraf * See the comments in forkx(), above. 191657b1f3dSraf */ 192657b1f3dSraf #pragma weak forkallx = _private_forkallx 193657b1f3dSraf #pragma weak _forkallx = _private_forkallx 194dfb96a4fSab pid_t 195657b1f3dSraf _private_forkallx(int flags) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1987c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1997c478bd9Sstevel@tonic-gate pid_t pid; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 2027c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 2037c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2047c478bd9Sstevel@tonic-gate return (-1); 2057c478bd9Sstevel@tonic-gate } 206657b1f3dSraf pid = __forkallx(flags); 2077c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2087c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2097c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate return (pid); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 214*2e145884Sraf sigoff(self); 215*2e145884Sraf if (self->ul_fork) { 216*2e145884Sraf sigon(self); 217*2e145884Sraf errno = EDEADLK; 2187c478bd9Sstevel@tonic-gate return (-1); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate self->ul_fork = 1; 221*2e145884Sraf 222*2e145884Sraf fork_lock_enter(); 2237c478bd9Sstevel@tonic-gate block_all_signals(self); 2247c478bd9Sstevel@tonic-gate suspend_fork(); 2257c478bd9Sstevel@tonic-gate 226657b1f3dSraf pid = __forkallx(flags); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (pid == 0) { 2297c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2307c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2317c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2327c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2337c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 234883492d5Sraf unregister_locks(); 2357c478bd9Sstevel@tonic-gate continue_fork(1); 2367c478bd9Sstevel@tonic-gate } else { 2377c478bd9Sstevel@tonic-gate continue_fork(0); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate restore_signals(self); 2407c478bd9Sstevel@tonic-gate fork_lock_exit(); 241*2e145884Sraf self->ul_fork = 0; 242*2e145884Sraf sigon(self); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate return (pid); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 247657b1f3dSraf #pragma weak forkall = _forkall 248657b1f3dSraf pid_t 249657b1f3dSraf _forkall(void) 250657b1f3dSraf { 251657b1f3dSraf return (_private_forkallx(0)); 252657b1f3dSraf } 253657b1f3dSraf 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * Hacks for system calls to provide cancellation 2567c478bd9Sstevel@tonic-gate * and improve java garbage collection. 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate #define PROLOGUE \ 2597c478bd9Sstevel@tonic-gate { \ 2607c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 2617c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 2627c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 2637c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 2647c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 2657c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 2667c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 2677c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED); \ 2687c478bd9Sstevel@tonic-gate } \ 2697c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate #define EPILOGUE \ 2737c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 2747c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 2757c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 2767c478bd9Sstevel@tonic-gate } \ 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 2817c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 2827c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 2837c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 2847c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 2877c478bd9Sstevel@tonic-gate PROLOGUE \ 2887c478bd9Sstevel@tonic-gate if (nocancel) \ 2897c478bd9Sstevel@tonic-gate return (function_call); \ 2907c478bd9Sstevel@tonic-gate rv = function_call; \ 2917c478bd9Sstevel@tonic-gate EPILOGUE \ 2927c478bd9Sstevel@tonic-gate return (rv); 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 2967c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 2977c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 2987c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 2997c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 3007c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 3017c478bd9Sstevel@tonic-gate * for the particular signal. 3027c478bd9Sstevel@tonic-gate * 3037c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 3047c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 3057c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 3087c478bd9Sstevel@tonic-gate { \ 3097c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 3107c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 3117c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 3127c478bd9Sstevel@tonic-gate if (sigmask) { \ 3137c478bd9Sstevel@tonic-gate block_all_signals(self); \ 3140293487cSraf self->ul_tmpmask.__sigbits[0] = sigmask->__sigbits[0]; \ 3150293487cSraf self->ul_tmpmask.__sigbits[1] = sigmask->__sigbits[1]; \ 3167c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 3177c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 3187c478bd9Sstevel@tonic-gate } \ 3197c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3207c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3217c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3227c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3237c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 3247c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3257c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 3267c478bd9Sstevel@tonic-gate restore_signals(self); \ 3277c478bd9Sstevel@tonic-gate } \ 3287c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED);\ 3297c478bd9Sstevel@tonic-gate } \ 3307c478bd9Sstevel@tonic-gate } \ 3317c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 3327c478bd9Sstevel@tonic-gate } \ 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 3377c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 3387c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 3397c478bd9Sstevel@tonic-gate * original signal mask ourself. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 3427c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3437c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3447c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3457c478bd9Sstevel@tonic-gate } \ 3467c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3477c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 3487c478bd9Sstevel@tonic-gate restore_signals(self); \ 3497c478bd9Sstevel@tonic-gate } \ 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 35234709573Sraf /* 353f841f6adSraf * Cancellation prologue and epilogue functions, 354f841f6adSraf * for cancellation points too complex to include here. 35534709573Sraf */ 35634709573Sraf void 35734709573Sraf _cancel_prologue(void) 35834709573Sraf { 35934709573Sraf ulwp_t *self = curthread; 36034709573Sraf 36134709573Sraf self->ul_cancel_prologue = (self->ul_vfork | self->ul_nocancel); 36234709573Sraf if (self->ul_cancel_prologue == 0) { 36334709573Sraf self->ul_save_async = self->ul_cancel_async; 36434709573Sraf if (!self->ul_cancel_disabled) { 36534709573Sraf self->ul_cancel_async = 1; 36634709573Sraf if (self->ul_cancel_pending) 36734709573Sraf _pthread_exit(PTHREAD_CANCELED); 36834709573Sraf } 36934709573Sraf self->ul_sp = stkptr(); 37034709573Sraf } 37134709573Sraf } 37234709573Sraf 37334709573Sraf void 37434709573Sraf _cancel_epilogue(void) 37534709573Sraf { 37634709573Sraf ulwp_t *self = curthread; 37734709573Sraf 37834709573Sraf if (self->ul_cancel_prologue == 0) { 37934709573Sraf self->ul_sp = 0; 38034709573Sraf self->ul_cancel_async = self->ul_save_async; 38134709573Sraf } 38234709573Sraf } 38334709573Sraf 3847c478bd9Sstevel@tonic-gate /* 3857c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 3867c478bd9Sstevel@tonic-gate */ 3877c478bd9Sstevel@tonic-gate int 3887c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 3897c478bd9Sstevel@tonic-gate { 3907c478bd9Sstevel@tonic-gate int error; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate PROLOGUE 3937c478bd9Sstevel@tonic-gate while ((error = __lwp_wait(tid, found)) == EINTR) 3947c478bd9Sstevel@tonic-gate ; 3957c478bd9Sstevel@tonic-gate EPILOGUE 3967c478bd9Sstevel@tonic-gate return (error); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate ssize_t 4007c478bd9Sstevel@tonic-gate read(int fd, void *buf, size_t size) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate extern ssize_t _read(int, void *, size_t); 4037c478bd9Sstevel@tonic-gate ssize_t rv; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate PERFORM(_read(fd, buf, size)) 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate ssize_t 4097c478bd9Sstevel@tonic-gate write(int fd, const void *buf, size_t size) 4107c478bd9Sstevel@tonic-gate { 4117c478bd9Sstevel@tonic-gate extern ssize_t _write(int, const void *, size_t); 4127c478bd9Sstevel@tonic-gate ssize_t rv; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate PERFORM(_write(fd, buf, size)) 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate int 4187c478bd9Sstevel@tonic-gate getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4197c478bd9Sstevel@tonic-gate int *flagsp) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate extern int _getmsg(int, struct strbuf *, struct strbuf *, int *); 4227c478bd9Sstevel@tonic-gate int rv; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate PERFORM(_getmsg(fd, ctlptr, dataptr, flagsp)) 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate int 4287c478bd9Sstevel@tonic-gate getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4297c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 4307c478bd9Sstevel@tonic-gate { 4317c478bd9Sstevel@tonic-gate extern int _getpmsg(int, struct strbuf *, struct strbuf *, 432*2e145884Sraf int *, int *); 4337c478bd9Sstevel@tonic-gate int rv; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate PERFORM(_getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate int 4397c478bd9Sstevel@tonic-gate putmsg(int fd, const struct strbuf *ctlptr, 4407c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4417c478bd9Sstevel@tonic-gate { 4427c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 443*2e145884Sraf const struct strbuf *, int); 4447c478bd9Sstevel@tonic-gate int rv; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags)) 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate int 4507c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 4517c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 454*2e145884Sraf const struct strbuf *, int); 4557c478bd9Sstevel@tonic-gate int rv; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate int 4617c478bd9Sstevel@tonic-gate putpmsg(int fd, const struct strbuf *ctlptr, 4627c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 4637c478bd9Sstevel@tonic-gate { 4647c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 465*2e145884Sraf const struct strbuf *, int, int); 4667c478bd9Sstevel@tonic-gate int rv; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags)) 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate int 4727c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 4737c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 476*2e145884Sraf const struct strbuf *, int, int); 4777c478bd9Sstevel@tonic-gate int rv; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 482f841f6adSraf #pragma weak nanosleep = _nanosleep 4837c478bd9Sstevel@tonic-gate int 484f841f6adSraf _nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 4857c478bd9Sstevel@tonic-gate { 4867c478bd9Sstevel@tonic-gate int error; 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate PROLOGUE 489f841f6adSraf error = __nanosleep(rqtp, rmtp); 4907c478bd9Sstevel@tonic-gate EPILOGUE 4917c478bd9Sstevel@tonic-gate if (error) { 4927c478bd9Sstevel@tonic-gate errno = error; 4937c478bd9Sstevel@tonic-gate return (-1); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate return (0); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 498f841f6adSraf #pragma weak clock_nanosleep = _clock_nanosleep 4997c478bd9Sstevel@tonic-gate int 500f841f6adSraf _clock_nanosleep(clockid_t clock_id, int flags, 5017c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 5027c478bd9Sstevel@tonic-gate { 5037c478bd9Sstevel@tonic-gate timespec_t reltime; 5047c478bd9Sstevel@tonic-gate hrtime_t start; 5057c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 5067c478bd9Sstevel@tonic-gate hrtime_t lapse; 5077c478bd9Sstevel@tonic-gate int error; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate switch (clock_id) { 5107c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 5117c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 5127c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 5137c478bd9Sstevel@tonic-gate return (ENOTSUP); 5147c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 5157c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 5167c478bd9Sstevel@tonic-gate break; 5177c478bd9Sstevel@tonic-gate default: 5187c478bd9Sstevel@tonic-gate return (EINVAL); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5217c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5227c478bd9Sstevel@tonic-gate rmtp = NULL; 5237c478bd9Sstevel@tonic-gate } else { 5247c478bd9Sstevel@tonic-gate reltime = *rqtp; 5257c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 5267c478bd9Sstevel@tonic-gate start = gethrtime(); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate restart: 5297c478bd9Sstevel@tonic-gate PROLOGUE 530f841f6adSraf error = __nanosleep(&reltime, rmtp); 5317c478bd9Sstevel@tonic-gate EPILOGUE 5327c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 5337c478bd9Sstevel@tonic-gate /* 5347c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 5357c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 5367c478bd9Sstevel@tonic-gate * the system clock. 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5397c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 5407c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 5417c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5427c478bd9Sstevel@tonic-gate goto restart; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate } else { 5457c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 546*2e145884Sraf rqtp->tv_nsec; 5477c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 5487c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 5497c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 5507c478bd9Sstevel@tonic-gate goto restart; 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 5557c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 5567c478bd9Sstevel@tonic-gate /* 5577c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 5587c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 5597c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 5607c478bd9Sstevel@tonic-gate * 5617c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 5627c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 5637c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 5647c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 5657c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 5667c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 5677c478bd9Sstevel@tonic-gate */ 5687c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5697c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 5707c478bd9Sstevel@tonic-gate goto restart; 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate return (error); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate #pragma weak sleep = _sleep 5767c478bd9Sstevel@tonic-gate unsigned int 5777c478bd9Sstevel@tonic-gate _sleep(unsigned int sec) 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate unsigned int rem = 0; 5807c478bd9Sstevel@tonic-gate int error; 5817c478bd9Sstevel@tonic-gate timespec_t ts; 5827c478bd9Sstevel@tonic-gate timespec_t tsr; 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 5857c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 5867c478bd9Sstevel@tonic-gate PROLOGUE 587f841f6adSraf error = __nanosleep(&ts, &tsr); 5887c478bd9Sstevel@tonic-gate EPILOGUE 5897c478bd9Sstevel@tonic-gate if (error == EINTR) { 5907c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 5917c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 5927c478bd9Sstevel@tonic-gate rem++; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate return (rem); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate #pragma weak usleep = _usleep 5987c478bd9Sstevel@tonic-gate int 5997c478bd9Sstevel@tonic-gate _usleep(useconds_t usec) 6007c478bd9Sstevel@tonic-gate { 6017c478bd9Sstevel@tonic-gate timespec_t ts; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 6047c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 6057c478bd9Sstevel@tonic-gate PROLOGUE 606f841f6adSraf (void) __nanosleep(&ts, NULL); 6077c478bd9Sstevel@tonic-gate EPILOGUE 6087c478bd9Sstevel@tonic-gate return (0); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate int 6127c478bd9Sstevel@tonic-gate close(int fildes) 6137c478bd9Sstevel@tonic-gate { 614f841f6adSraf extern void _aio_close(int); 6157c478bd9Sstevel@tonic-gate extern int _close(int); 6167c478bd9Sstevel@tonic-gate int rv; 6177c478bd9Sstevel@tonic-gate 618f841f6adSraf _aio_close(fildes); 6197c478bd9Sstevel@tonic-gate PERFORM(_close(fildes)) 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate int 6237c478bd9Sstevel@tonic-gate creat(const char *path, mode_t mode) 6247c478bd9Sstevel@tonic-gate { 6257c478bd9Sstevel@tonic-gate extern int _creat(const char *, mode_t); 6267c478bd9Sstevel@tonic-gate int rv; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate PERFORM(_creat(path, mode)) 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate #if !defined(_LP64) 6327c478bd9Sstevel@tonic-gate int 6337c478bd9Sstevel@tonic-gate creat64(const char *path, mode_t mode) 6347c478bd9Sstevel@tonic-gate { 6357c478bd9Sstevel@tonic-gate extern int _creat64(const char *, mode_t); 6367c478bd9Sstevel@tonic-gate int rv; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate PERFORM(_creat64(path, mode)) 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate int 6437c478bd9Sstevel@tonic-gate fcntl(int fildes, int cmd, ...) 6447c478bd9Sstevel@tonic-gate { 6457c478bd9Sstevel@tonic-gate extern int _fcntl(int, int, ...); 6467c478bd9Sstevel@tonic-gate intptr_t arg; 6477c478bd9Sstevel@tonic-gate int rv; 6487c478bd9Sstevel@tonic-gate va_list ap; 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate va_start(ap, cmd); 6517c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 6527c478bd9Sstevel@tonic-gate va_end(ap); 6537c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 6547c478bd9Sstevel@tonic-gate return (_fcntl(fildes, cmd, arg)); 6557c478bd9Sstevel@tonic-gate PERFORM(_fcntl(fildes, cmd, arg)) 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6581f8cf95fSraf int 6591f8cf95fSraf fdatasync(int fildes) 6601f8cf95fSraf { 6611f8cf95fSraf extern int _fdatasync(int); 6621f8cf95fSraf int rv; 6631f8cf95fSraf 6641f8cf95fSraf PERFORM(_fdatasync(fildes)) 6651f8cf95fSraf } 6661f8cf95fSraf 6677c478bd9Sstevel@tonic-gate int 6687c478bd9Sstevel@tonic-gate fsync(int fildes) 6697c478bd9Sstevel@tonic-gate { 6707c478bd9Sstevel@tonic-gate extern int _fsync(int); 6717c478bd9Sstevel@tonic-gate int rv; 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate PERFORM(_fsync(fildes)) 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate int 6777c478bd9Sstevel@tonic-gate lockf(int fildes, int function, off_t size) 6787c478bd9Sstevel@tonic-gate { 6797c478bd9Sstevel@tonic-gate extern int _lockf(int, int, off_t); 6807c478bd9Sstevel@tonic-gate int rv; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate PERFORM(_lockf(fildes, function, size)) 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate #if !defined(_LP64) 6867c478bd9Sstevel@tonic-gate int 6877c478bd9Sstevel@tonic-gate lockf64(int fildes, int function, off64_t size) 6887c478bd9Sstevel@tonic-gate { 6897c478bd9Sstevel@tonic-gate extern int _lockf64(int, int, off64_t); 6907c478bd9Sstevel@tonic-gate int rv; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate PERFORM(_lockf64(fildes, function, size)) 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate ssize_t 6977c478bd9Sstevel@tonic-gate msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 6987c478bd9Sstevel@tonic-gate { 6997c478bd9Sstevel@tonic-gate extern ssize_t _msgrcv(int, void *, size_t, long, int); 7007c478bd9Sstevel@tonic-gate ssize_t rv; 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate PERFORM(_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate int 7067c478bd9Sstevel@tonic-gate msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 7077c478bd9Sstevel@tonic-gate { 7087c478bd9Sstevel@tonic-gate extern int _msgsnd(int, const void *, size_t, int); 7097c478bd9Sstevel@tonic-gate int rv; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate PERFORM(_msgsnd(msqid, msgp, msgsz, msgflg)) 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate int 7157c478bd9Sstevel@tonic-gate msync(caddr_t addr, size_t len, int flags) 7167c478bd9Sstevel@tonic-gate { 7177c478bd9Sstevel@tonic-gate extern int _msync(caddr_t, size_t, int); 7187c478bd9Sstevel@tonic-gate int rv; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate PERFORM(_msync(addr, len, flags)) 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate int 7247c478bd9Sstevel@tonic-gate open(const char *path, int oflag, ...) 7257c478bd9Sstevel@tonic-gate { 7267c478bd9Sstevel@tonic-gate extern int _open(const char *, int, ...); 7277c478bd9Sstevel@tonic-gate mode_t mode; 7287c478bd9Sstevel@tonic-gate int rv; 7297c478bd9Sstevel@tonic-gate va_list ap; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7327c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7337c478bd9Sstevel@tonic-gate va_end(ap); 7347c478bd9Sstevel@tonic-gate PERFORM(_open(path, oflag, mode)) 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7387c478bd9Sstevel@tonic-gate int 7397c478bd9Sstevel@tonic-gate open64(const char *path, int oflag, ...) 7407c478bd9Sstevel@tonic-gate { 7417c478bd9Sstevel@tonic-gate extern int _open64(const char *, int, ...); 7427c478bd9Sstevel@tonic-gate mode_t mode; 7437c478bd9Sstevel@tonic-gate int rv; 7447c478bd9Sstevel@tonic-gate va_list ap; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7477c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7487c478bd9Sstevel@tonic-gate va_end(ap); 7497c478bd9Sstevel@tonic-gate PERFORM(_open64(path, oflag, mode)) 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate int 7547c478bd9Sstevel@tonic-gate pause(void) 7557c478bd9Sstevel@tonic-gate { 7567c478bd9Sstevel@tonic-gate extern int _pause(void); 7577c478bd9Sstevel@tonic-gate int rv; 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate PERFORM(_pause()) 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate ssize_t 7637c478bd9Sstevel@tonic-gate pread(int fildes, void *buf, size_t nbyte, off_t offset) 7647c478bd9Sstevel@tonic-gate { 7657c478bd9Sstevel@tonic-gate extern ssize_t _pread(int, void *, size_t, off_t); 7667c478bd9Sstevel@tonic-gate ssize_t rv; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate PERFORM(_pread(fildes, buf, nbyte, offset)) 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7727c478bd9Sstevel@tonic-gate ssize_t 7737c478bd9Sstevel@tonic-gate pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 7747c478bd9Sstevel@tonic-gate { 7757c478bd9Sstevel@tonic-gate extern ssize_t _pread64(int, void *, size_t, off64_t); 7767c478bd9Sstevel@tonic-gate ssize_t rv; 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate PERFORM(_pread64(fildes, buf, nbyte, offset)) 7797c478bd9Sstevel@tonic-gate } 7807c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate ssize_t 7837c478bd9Sstevel@tonic-gate pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 7847c478bd9Sstevel@tonic-gate { 7857c478bd9Sstevel@tonic-gate extern ssize_t _pwrite(int, const void *, size_t, off_t); 7867c478bd9Sstevel@tonic-gate ssize_t rv; 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate PERFORM(_pwrite(fildes, buf, nbyte, offset)) 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7927c478bd9Sstevel@tonic-gate ssize_t 7937c478bd9Sstevel@tonic-gate pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 7947c478bd9Sstevel@tonic-gate { 7957c478bd9Sstevel@tonic-gate extern ssize_t _pwrite64(int, const void *, size_t, off64_t); 7967c478bd9Sstevel@tonic-gate ssize_t rv; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate PERFORM(_pwrite64(fildes, buf, nbyte, offset)) 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate ssize_t 8037c478bd9Sstevel@tonic-gate readv(int fildes, const struct iovec *iov, int iovcnt) 8047c478bd9Sstevel@tonic-gate { 8057c478bd9Sstevel@tonic-gate extern ssize_t _readv(int, const struct iovec *, int); 8067c478bd9Sstevel@tonic-gate ssize_t rv; 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate PERFORM(_readv(fildes, iov, iovcnt)) 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate int 8127c478bd9Sstevel@tonic-gate sigpause(int sig) 8137c478bd9Sstevel@tonic-gate { 8147c478bd9Sstevel@tonic-gate extern int _sigpause(int); 8157c478bd9Sstevel@tonic-gate int rv; 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate PERFORM(_sigpause(sig)) 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate #pragma weak sigsuspend = _sigsuspend 8217c478bd9Sstevel@tonic-gate int 8227c478bd9Sstevel@tonic-gate _sigsuspend(const sigset_t *set) 8237c478bd9Sstevel@tonic-gate { 8247c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 8257c478bd9Sstevel@tonic-gate int rv; 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 8287c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 8297c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8307c478bd9Sstevel@tonic-gate return (rv); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate int 8347c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 8357c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 8367c478bd9Sstevel@tonic-gate { 8377c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 838*2e145884Sraf const sigset_t *); 8397c478bd9Sstevel@tonic-gate int rv; 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 8427c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 8437c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8447c478bd9Sstevel@tonic-gate return (rv); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 847f841f6adSraf #pragma weak sigtimedwait = _sigtimedwait 8487c478bd9Sstevel@tonic-gate int 849f841f6adSraf _sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout) 8507c478bd9Sstevel@tonic-gate { 851f841f6adSraf extern int __sigtimedwait(const sigset_t *, siginfo_t *, 852*2e145884Sraf const timespec_t *); 8537c478bd9Sstevel@tonic-gate siginfo_t info; 8547c478bd9Sstevel@tonic-gate int sig; 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate PROLOGUE 857f841f6adSraf sig = __sigtimedwait(set, &info, timeout); 8587c478bd9Sstevel@tonic-gate if (sig == SIGCANCEL && 8597c478bd9Sstevel@tonic-gate (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 8607c478bd9Sstevel@tonic-gate do_sigcancel(); 8617c478bd9Sstevel@tonic-gate errno = EINTR; 8627c478bd9Sstevel@tonic-gate sig = -1; 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate EPILOGUE 8657c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 8660293487cSraf (void) _private_memcpy(infop, &info, sizeof (*infop)); 8677c478bd9Sstevel@tonic-gate return (sig); 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate #pragma weak sigwait = _sigwait 8717c478bd9Sstevel@tonic-gate int 8727c478bd9Sstevel@tonic-gate _sigwait(sigset_t *set) 8737c478bd9Sstevel@tonic-gate { 874f841f6adSraf return (_sigtimedwait(set, NULL, NULL)); 875f841f6adSraf } 876f841f6adSraf 877f841f6adSraf #pragma weak sigwaitinfo = _sigwaitinfo 878f841f6adSraf int 879f841f6adSraf _sigwaitinfo(const sigset_t *set, siginfo_t *info) 880f841f6adSraf { 881f841f6adSraf return (_sigtimedwait(set, info, NULL)); 882f841f6adSraf } 883f841f6adSraf 884f841f6adSraf #pragma weak sigqueue = _sigqueue 885f841f6adSraf int 886f841f6adSraf _sigqueue(pid_t pid, int signo, const union sigval value) 887f841f6adSraf { 888f841f6adSraf extern int __sigqueue(pid_t pid, int signo, 889*2e145884Sraf /* const union sigval */ void *value, int si_code, int block); 890f841f6adSraf return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0)); 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate int 8947c478bd9Sstevel@tonic-gate tcdrain(int fildes) 8957c478bd9Sstevel@tonic-gate { 8967c478bd9Sstevel@tonic-gate extern int _tcdrain(int); 8977c478bd9Sstevel@tonic-gate int rv; 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate PERFORM(_tcdrain(fildes)) 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate pid_t 9037c478bd9Sstevel@tonic-gate wait(int *stat_loc) 9047c478bd9Sstevel@tonic-gate { 9057c478bd9Sstevel@tonic-gate extern pid_t _wait(int *); 9067c478bd9Sstevel@tonic-gate pid_t rv; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate PERFORM(_wait(stat_loc)) 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate pid_t 9127c478bd9Sstevel@tonic-gate wait3(int *statusp, int options, struct rusage *rusage) 9137c478bd9Sstevel@tonic-gate { 9147c478bd9Sstevel@tonic-gate extern pid_t _wait3(int *, int, struct rusage *); 9157c478bd9Sstevel@tonic-gate pid_t rv; 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate PERFORM(_wait3(statusp, options, rusage)) 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate int 9217c478bd9Sstevel@tonic-gate waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate extern int _waitid(idtype_t, id_t, siginfo_t *, int); 9247c478bd9Sstevel@tonic-gate int rv; 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate PERFORM(_waitid(idtype, id, infop, options)) 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate 929e8031f0aSraf /* 930e8031f0aSraf * waitpid_cancel() is a libc-private symbol for internal use 931e8031f0aSraf * where cancellation semantics is desired (see system()). 932e8031f0aSraf */ 933e8031f0aSraf #pragma weak waitpid_cancel = waitpid 9347c478bd9Sstevel@tonic-gate pid_t 9357c478bd9Sstevel@tonic-gate waitpid(pid_t pid, int *stat_loc, int options) 9367c478bd9Sstevel@tonic-gate { 9377c478bd9Sstevel@tonic-gate extern pid_t _waitpid(pid_t, int *, int); 9387c478bd9Sstevel@tonic-gate pid_t rv; 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate PERFORM(_waitpid(pid, stat_loc, options)) 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate ssize_t 9447c478bd9Sstevel@tonic-gate writev(int fildes, const struct iovec *iov, int iovcnt) 9457c478bd9Sstevel@tonic-gate { 9467c478bd9Sstevel@tonic-gate extern ssize_t _writev(int, const struct iovec *, int); 9477c478bd9Sstevel@tonic-gate ssize_t rv; 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate PERFORM(_writev(fildes, iov, iovcnt)) 9507c478bd9Sstevel@tonic-gate } 951