1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "lint.h" 30*7c478bd9Sstevel@tonic-gate #include "thr_uberdata.h" 31*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 32*7c478bd9Sstevel@tonic-gate #include <poll.h> 33*7c478bd9Sstevel@tonic-gate #include <stropts.h> 34*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate * fork_lock is special -- We can't use lmutex_lock() (and thereby enter 39*7c478bd9Sstevel@tonic-gate * a critical region) because the second thread to reach this point would 40*7c478bd9Sstevel@tonic-gate * become unstoppable and the first thread would hang waiting for the 41*7c478bd9Sstevel@tonic-gate * second thread to stop itself. Therefore we don't use lmutex_lock() in 42*7c478bd9Sstevel@tonic-gate * fork_lock_enter(), but we do defer signals (the other form of concurrency). 43*7c478bd9Sstevel@tonic-gate * 44*7c478bd9Sstevel@tonic-gate * fork_lock_enter() does triple-duty. Not only does it serialize 45*7c478bd9Sstevel@tonic-gate * calls to fork() and forkall(), but it also serializes calls to 46*7c478bd9Sstevel@tonic-gate * thr_suspend() (fork() and forkall() also suspend other threads), 47*7c478bd9Sstevel@tonic-gate * and furthermore it serializes I18N calls to functions in other 48*7c478bd9Sstevel@tonic-gate * dlopen()ed L10N objects that might be calling malloc()/free(). 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate static void 52*7c478bd9Sstevel@tonic-gate fork_lock_error(const char *who) 53*7c478bd9Sstevel@tonic-gate { 54*7c478bd9Sstevel@tonic-gate char msg[200]; 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate (void) strlcpy(msg, "deadlock condition: ", sizeof (msg)); 57*7c478bd9Sstevel@tonic-gate (void) strlcat(msg, who, sizeof (msg)); 58*7c478bd9Sstevel@tonic-gate (void) strlcat(msg, "() called from a fork handler", sizeof (msg)); 59*7c478bd9Sstevel@tonic-gate thread_error(msg); 60*7c478bd9Sstevel@tonic-gate } 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate int 63*7c478bd9Sstevel@tonic-gate fork_lock_enter(const char *who) 64*7c478bd9Sstevel@tonic-gate { 65*7c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 66*7c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 67*7c478bd9Sstevel@tonic-gate int error = 0; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 70*7c478bd9Sstevel@tonic-gate sigoff(self); 71*7c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 72*7c478bd9Sstevel@tonic-gate while (udp->fork_count) { 73*7c478bd9Sstevel@tonic-gate if (udp->fork_owner == self) { 74*7c478bd9Sstevel@tonic-gate /* 75*7c478bd9Sstevel@tonic-gate * This is like a recursive lock except that we 76*7c478bd9Sstevel@tonic-gate * inform the caller if we have been called from 77*7c478bd9Sstevel@tonic-gate * a fork handler and let it deal with that fact. 78*7c478bd9Sstevel@tonic-gate */ 79*7c478bd9Sstevel@tonic-gate if (self->ul_fork) { 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * We have been called from a fork handler. 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate if (who != NULL && 84*7c478bd9Sstevel@tonic-gate udp->uberflags.uf_thread_error_detection) 85*7c478bd9Sstevel@tonic-gate fork_lock_error(who); 86*7c478bd9Sstevel@tonic-gate error = EDEADLK; 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate break; 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate ASSERT(self->ul_fork == 0); 91*7c478bd9Sstevel@tonic-gate (void) _cond_wait(&udp->fork_cond, &udp->fork_lock); 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate udp->fork_owner = self; 94*7c478bd9Sstevel@tonic-gate udp->fork_count++; 95*7c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 96*7c478bd9Sstevel@tonic-gate return (error); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate void 100*7c478bd9Sstevel@tonic-gate fork_lock_exit(void) 101*7c478bd9Sstevel@tonic-gate { 102*7c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 103*7c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 106*7c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 107*7c478bd9Sstevel@tonic-gate ASSERT(udp->fork_count != 0 && udp->fork_owner == self); 108*7c478bd9Sstevel@tonic-gate if (--udp->fork_count == 0) { 109*7c478bd9Sstevel@tonic-gate udp->fork_owner = NULL; 110*7c478bd9Sstevel@tonic-gate (void) _cond_signal(&udp->fork_cond); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 113*7c478bd9Sstevel@tonic-gate sigon(self); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* 117*7c478bd9Sstevel@tonic-gate * fork() is fork1() for both Posix threads and Solaris threads. 118*7c478bd9Sstevel@tonic-gate * The forkall() interface exists for applications that require 119*7c478bd9Sstevel@tonic-gate * the semantics of replicating all threads. 120*7c478bd9Sstevel@tonic-gate */ 121*7c478bd9Sstevel@tonic-gate #pragma weak fork = _fork1 122*7c478bd9Sstevel@tonic-gate #pragma weak _fork = _fork1 123*7c478bd9Sstevel@tonic-gate #pragma weak fork1 = _fork1 124*7c478bd9Sstevel@tonic-gate pid_t 125*7c478bd9Sstevel@tonic-gate _fork1(void) 126*7c478bd9Sstevel@tonic-gate { 127*7c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 128*7c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 129*7c478bd9Sstevel@tonic-gate pid_t pid; 130*7c478bd9Sstevel@tonic-gate int error; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 135*7c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 136*7c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 137*7c478bd9Sstevel@tonic-gate * must never call fork(). 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 140*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 141*7c478bd9Sstevel@tonic-gate return (-1); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate pid = __fork1(); 144*7c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 145*7c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 146*7c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate return (pid); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("fork")) != 0) { 152*7c478bd9Sstevel@tonic-gate /* 153*7c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate fork_lock_exit(); 156*7c478bd9Sstevel@tonic-gate errno = error; 157*7c478bd9Sstevel@tonic-gate return (-1); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate self->ul_fork = 1; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 163*7c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 164*7c478bd9Sstevel@tonic-gate * internal libc locks while invoking them. The fork_lock_enter() 165*7c478bd9Sstevel@tonic-gate * function serializes fork(), thr_suspend(), pthread_atfork() and 166*7c478bd9Sstevel@tonic-gate * dlclose() (which destroys whatever pthread_atfork() functions 167*7c478bd9Sstevel@tonic-gate * the library may have set up). If one of these pthread_atfork() 168*7c478bd9Sstevel@tonic-gate * functions attempts to fork or suspend another thread or call 169*7c478bd9Sstevel@tonic-gate * pthread_atfork() or dlclose a library, it will detect a deadlock 170*7c478bd9Sstevel@tonic-gate * in fork_lock_enter(). Otherwise, the pthread_atfork() functions 171*7c478bd9Sstevel@tonic-gate * are free to do anything they please (except they will not 172*7c478bd9Sstevel@tonic-gate * receive any signals). 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate _prefork_handler(); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * Block all signals. 178*7c478bd9Sstevel@tonic-gate * Just deferring them via sigon() is not enough. 179*7c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 180*7c478bd9Sstevel@tonic-gate * that was actually sent to the parent before __fork1(). 181*7c478bd9Sstevel@tonic-gate */ 182*7c478bd9Sstevel@tonic-gate block_all_signals(self); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate /* 185*7c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 186*7c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 187*7c478bd9Sstevel@tonic-gate * Thus, we are assured that no library locks are held 188*7c478bd9Sstevel@tonic-gate * while we invoke fork1() from the current thread. 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 191*7c478bd9Sstevel@tonic-gate suspend_fork(); 192*7c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate pid = __fork1(); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 197*7c478bd9Sstevel@tonic-gate /* 198*7c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 199*7c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 200*7c478bd9Sstevel@tonic-gate * Because we blocked all signals before __fork1(), a 201*7c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 202*7c478bd9Sstevel@tonic-gate */ 203*7c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 204*7c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 205*7c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 206*7c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 207*7c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 208*7c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 209*7c478bd9Sstevel@tonic-gate _postfork1_child(); 210*7c478bd9Sstevel@tonic-gate restore_signals(self); 211*7c478bd9Sstevel@tonic-gate _postfork_child_handler(); 212*7c478bd9Sstevel@tonic-gate } else { 213*7c478bd9Sstevel@tonic-gate /* restart all threads that were suspended for fork1() */ 214*7c478bd9Sstevel@tonic-gate continue_fork(0); 215*7c478bd9Sstevel@tonic-gate restore_signals(self); 216*7c478bd9Sstevel@tonic-gate _postfork_parent_handler(); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate self->ul_fork = 0; 220*7c478bd9Sstevel@tonic-gate fork_lock_exit(); 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate return (pid); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * Much of the logic here is the same as in fork1(). 227*7c478bd9Sstevel@tonic-gate * See the comments in fork1(), above. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate #pragma weak forkall = _forkall 230*7c478bd9Sstevel@tonic-gate pid_t 231*7c478bd9Sstevel@tonic-gate _forkall(void) 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 234*7c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 235*7c478bd9Sstevel@tonic-gate pid_t pid; 236*7c478bd9Sstevel@tonic-gate int error; 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 239*7c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 240*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 241*7c478bd9Sstevel@tonic-gate return (-1); 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate pid = __forkall(); 244*7c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 245*7c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 246*7c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate return (pid); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("forkall")) != 0) { 252*7c478bd9Sstevel@tonic-gate fork_lock_exit(); 253*7c478bd9Sstevel@tonic-gate errno = error; 254*7c478bd9Sstevel@tonic-gate return (-1); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate self->ul_fork = 1; 257*7c478bd9Sstevel@tonic-gate block_all_signals(self); 258*7c478bd9Sstevel@tonic-gate suspend_fork(); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate pid = __forkall(); 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate if (pid == 0) { 263*7c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 264*7c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 265*7c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 266*7c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 267*7c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 268*7c478bd9Sstevel@tonic-gate continue_fork(1); 269*7c478bd9Sstevel@tonic-gate } else { 270*7c478bd9Sstevel@tonic-gate continue_fork(0); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate restore_signals(self); 273*7c478bd9Sstevel@tonic-gate self->ul_fork = 0; 274*7c478bd9Sstevel@tonic-gate fork_lock_exit(); 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate return (pid); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * Hacks for system calls to provide cancellation 281*7c478bd9Sstevel@tonic-gate * and improve java garbage collection. 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate #define PROLOGUE \ 284*7c478bd9Sstevel@tonic-gate { \ 285*7c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 286*7c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 287*7c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 288*7c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 289*7c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 290*7c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 291*7c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 292*7c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED); \ 293*7c478bd9Sstevel@tonic-gate } \ 294*7c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate #define EPILOGUE \ 298*7c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 299*7c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 300*7c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 301*7c478bd9Sstevel@tonic-gate } \ 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 306*7c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 307*7c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 308*7c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 309*7c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 312*7c478bd9Sstevel@tonic-gate PROLOGUE \ 313*7c478bd9Sstevel@tonic-gate if (nocancel) \ 314*7c478bd9Sstevel@tonic-gate return (function_call); \ 315*7c478bd9Sstevel@tonic-gate rv = function_call; \ 316*7c478bd9Sstevel@tonic-gate EPILOGUE \ 317*7c478bd9Sstevel@tonic-gate return (rv); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* 320*7c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 321*7c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 322*7c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 323*7c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 324*7c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 325*7c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 326*7c478bd9Sstevel@tonic-gate * for the particular signal. 327*7c478bd9Sstevel@tonic-gate * 328*7c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 329*7c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 330*7c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 331*7c478bd9Sstevel@tonic-gate */ 332*7c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 333*7c478bd9Sstevel@tonic-gate { \ 334*7c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 335*7c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 336*7c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 337*7c478bd9Sstevel@tonic-gate if (sigmask) { \ 338*7c478bd9Sstevel@tonic-gate block_all_signals(self); \ 339*7c478bd9Sstevel@tonic-gate self->ul_tmpmask = *sigmask; \ 340*7c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 341*7c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 342*7c478bd9Sstevel@tonic-gate } \ 343*7c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 344*7c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 345*7c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 346*7c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 347*7c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 348*7c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 349*7c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 350*7c478bd9Sstevel@tonic-gate restore_signals(self); \ 351*7c478bd9Sstevel@tonic-gate } \ 352*7c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED);\ 353*7c478bd9Sstevel@tonic-gate } \ 354*7c478bd9Sstevel@tonic-gate } \ 355*7c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 356*7c478bd9Sstevel@tonic-gate } \ 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate /* 360*7c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 361*7c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 362*7c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 363*7c478bd9Sstevel@tonic-gate * original signal mask ourself. 364*7c478bd9Sstevel@tonic-gate */ 365*7c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 366*7c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 367*7c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 368*7c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 369*7c478bd9Sstevel@tonic-gate } \ 370*7c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 371*7c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 372*7c478bd9Sstevel@tonic-gate restore_signals(self); \ 373*7c478bd9Sstevel@tonic-gate } \ 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 378*7c478bd9Sstevel@tonic-gate */ 379*7c478bd9Sstevel@tonic-gate int 380*7c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 381*7c478bd9Sstevel@tonic-gate { 382*7c478bd9Sstevel@tonic-gate int error; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate PROLOGUE 385*7c478bd9Sstevel@tonic-gate while ((error = __lwp_wait(tid, found)) == EINTR) 386*7c478bd9Sstevel@tonic-gate ; 387*7c478bd9Sstevel@tonic-gate EPILOGUE 388*7c478bd9Sstevel@tonic-gate return (error); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate ssize_t 392*7c478bd9Sstevel@tonic-gate read(int fd, void *buf, size_t size) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate extern ssize_t _read(int, void *, size_t); 395*7c478bd9Sstevel@tonic-gate ssize_t rv; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate PERFORM(_read(fd, buf, size)) 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate ssize_t 401*7c478bd9Sstevel@tonic-gate write(int fd, const void *buf, size_t size) 402*7c478bd9Sstevel@tonic-gate { 403*7c478bd9Sstevel@tonic-gate extern ssize_t _write(int, const void *, size_t); 404*7c478bd9Sstevel@tonic-gate ssize_t rv; 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate PERFORM(_write(fd, buf, size)) 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate int 410*7c478bd9Sstevel@tonic-gate getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 411*7c478bd9Sstevel@tonic-gate int *flagsp) 412*7c478bd9Sstevel@tonic-gate { 413*7c478bd9Sstevel@tonic-gate extern int _getmsg(int, struct strbuf *, struct strbuf *, int *); 414*7c478bd9Sstevel@tonic-gate int rv; 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate PERFORM(_getmsg(fd, ctlptr, dataptr, flagsp)) 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate int 420*7c478bd9Sstevel@tonic-gate getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 421*7c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 422*7c478bd9Sstevel@tonic-gate { 423*7c478bd9Sstevel@tonic-gate extern int _getpmsg(int, struct strbuf *, struct strbuf *, 424*7c478bd9Sstevel@tonic-gate int *, int *); 425*7c478bd9Sstevel@tonic-gate int rv; 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate PERFORM(_getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate int 431*7c478bd9Sstevel@tonic-gate putmsg(int fd, const struct strbuf *ctlptr, 432*7c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 433*7c478bd9Sstevel@tonic-gate { 434*7c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 435*7c478bd9Sstevel@tonic-gate const struct strbuf *, int); 436*7c478bd9Sstevel@tonic-gate int rv; 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags)) 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate int 442*7c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 443*7c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 444*7c478bd9Sstevel@tonic-gate { 445*7c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 446*7c478bd9Sstevel@tonic-gate const struct strbuf *, int); 447*7c478bd9Sstevel@tonic-gate int rv; 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate int 453*7c478bd9Sstevel@tonic-gate putpmsg(int fd, const struct strbuf *ctlptr, 454*7c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 457*7c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 458*7c478bd9Sstevel@tonic-gate int rv; 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags)) 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate int 464*7c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 465*7c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 466*7c478bd9Sstevel@tonic-gate { 467*7c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 468*7c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 469*7c478bd9Sstevel@tonic-gate int rv; 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate int 475*7c478bd9Sstevel@tonic-gate __nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 476*7c478bd9Sstevel@tonic-gate { 477*7c478bd9Sstevel@tonic-gate int error; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate PROLOGUE 480*7c478bd9Sstevel@tonic-gate error = ___nanosleep(rqtp, rmtp); 481*7c478bd9Sstevel@tonic-gate EPILOGUE 482*7c478bd9Sstevel@tonic-gate if (error) { 483*7c478bd9Sstevel@tonic-gate errno = error; 484*7c478bd9Sstevel@tonic-gate return (-1); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate return (0); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate int 490*7c478bd9Sstevel@tonic-gate __clock_nanosleep(clockid_t clock_id, int flags, 491*7c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 492*7c478bd9Sstevel@tonic-gate { 493*7c478bd9Sstevel@tonic-gate timespec_t reltime; 494*7c478bd9Sstevel@tonic-gate hrtime_t start; 495*7c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 496*7c478bd9Sstevel@tonic-gate hrtime_t lapse; 497*7c478bd9Sstevel@tonic-gate int error; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate switch (clock_id) { 500*7c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 501*7c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 502*7c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 503*7c478bd9Sstevel@tonic-gate return (ENOTSUP); 504*7c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 505*7c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 506*7c478bd9Sstevel@tonic-gate break; 507*7c478bd9Sstevel@tonic-gate default: 508*7c478bd9Sstevel@tonic-gate return (EINVAL); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 511*7c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 512*7c478bd9Sstevel@tonic-gate rmtp = NULL; 513*7c478bd9Sstevel@tonic-gate } else { 514*7c478bd9Sstevel@tonic-gate reltime = *rqtp; 515*7c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 516*7c478bd9Sstevel@tonic-gate start = gethrtime(); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate restart: 519*7c478bd9Sstevel@tonic-gate PROLOGUE 520*7c478bd9Sstevel@tonic-gate error = ___nanosleep(&reltime, rmtp); 521*7c478bd9Sstevel@tonic-gate EPILOGUE 522*7c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 523*7c478bd9Sstevel@tonic-gate /* 524*7c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 525*7c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 526*7c478bd9Sstevel@tonic-gate * the system clock. 527*7c478bd9Sstevel@tonic-gate */ 528*7c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 529*7c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 530*7c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 531*7c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 532*7c478bd9Sstevel@tonic-gate goto restart; 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate } else { 535*7c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 536*7c478bd9Sstevel@tonic-gate rqtp->tv_nsec; 537*7c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 538*7c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 539*7c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 540*7c478bd9Sstevel@tonic-gate goto restart; 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 545*7c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 546*7c478bd9Sstevel@tonic-gate /* 547*7c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 548*7c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 549*7c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 550*7c478bd9Sstevel@tonic-gate * 551*7c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 552*7c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 553*7c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 554*7c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 555*7c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 556*7c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 557*7c478bd9Sstevel@tonic-gate */ 558*7c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 559*7c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 560*7c478bd9Sstevel@tonic-gate goto restart; 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate return (error); 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate #pragma weak sleep = _sleep 566*7c478bd9Sstevel@tonic-gate unsigned int 567*7c478bd9Sstevel@tonic-gate _sleep(unsigned int sec) 568*7c478bd9Sstevel@tonic-gate { 569*7c478bd9Sstevel@tonic-gate unsigned int rem = 0; 570*7c478bd9Sstevel@tonic-gate int error; 571*7c478bd9Sstevel@tonic-gate timespec_t ts; 572*7c478bd9Sstevel@tonic-gate timespec_t tsr; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 575*7c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 576*7c478bd9Sstevel@tonic-gate PROLOGUE 577*7c478bd9Sstevel@tonic-gate error = ___nanosleep(&ts, &tsr); 578*7c478bd9Sstevel@tonic-gate EPILOGUE 579*7c478bd9Sstevel@tonic-gate if (error == EINTR) { 580*7c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 581*7c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 582*7c478bd9Sstevel@tonic-gate rem++; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate return (rem); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate #pragma weak usleep = _usleep 588*7c478bd9Sstevel@tonic-gate int 589*7c478bd9Sstevel@tonic-gate _usleep(useconds_t usec) 590*7c478bd9Sstevel@tonic-gate { 591*7c478bd9Sstevel@tonic-gate timespec_t ts; 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 594*7c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 595*7c478bd9Sstevel@tonic-gate PROLOGUE 596*7c478bd9Sstevel@tonic-gate (void) ___nanosleep(&ts, NULL); 597*7c478bd9Sstevel@tonic-gate EPILOGUE 598*7c478bd9Sstevel@tonic-gate return (0); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate int 602*7c478bd9Sstevel@tonic-gate close(int fildes) 603*7c478bd9Sstevel@tonic-gate { 604*7c478bd9Sstevel@tonic-gate extern int _close(int); 605*7c478bd9Sstevel@tonic-gate int rv; 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate PERFORM(_close(fildes)) 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate int 611*7c478bd9Sstevel@tonic-gate creat(const char *path, mode_t mode) 612*7c478bd9Sstevel@tonic-gate { 613*7c478bd9Sstevel@tonic-gate extern int _creat(const char *, mode_t); 614*7c478bd9Sstevel@tonic-gate int rv; 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate PERFORM(_creat(path, mode)) 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) 620*7c478bd9Sstevel@tonic-gate int 621*7c478bd9Sstevel@tonic-gate creat64(const char *path, mode_t mode) 622*7c478bd9Sstevel@tonic-gate { 623*7c478bd9Sstevel@tonic-gate extern int _creat64(const char *, mode_t); 624*7c478bd9Sstevel@tonic-gate int rv; 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate PERFORM(_creat64(path, mode)) 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate int 631*7c478bd9Sstevel@tonic-gate fcntl(int fildes, int cmd, ...) 632*7c478bd9Sstevel@tonic-gate { 633*7c478bd9Sstevel@tonic-gate extern int _fcntl(int, int, ...); 634*7c478bd9Sstevel@tonic-gate intptr_t arg; 635*7c478bd9Sstevel@tonic-gate int rv; 636*7c478bd9Sstevel@tonic-gate va_list ap; 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate va_start(ap, cmd); 639*7c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 640*7c478bd9Sstevel@tonic-gate va_end(ap); 641*7c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 642*7c478bd9Sstevel@tonic-gate return (_fcntl(fildes, cmd, arg)); 643*7c478bd9Sstevel@tonic-gate PERFORM(_fcntl(fildes, cmd, arg)) 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate int 647*7c478bd9Sstevel@tonic-gate fsync(int fildes) 648*7c478bd9Sstevel@tonic-gate { 649*7c478bd9Sstevel@tonic-gate extern int _fsync(int); 650*7c478bd9Sstevel@tonic-gate int rv; 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate PERFORM(_fsync(fildes)) 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate int 656*7c478bd9Sstevel@tonic-gate lockf(int fildes, int function, off_t size) 657*7c478bd9Sstevel@tonic-gate { 658*7c478bd9Sstevel@tonic-gate extern int _lockf(int, int, off_t); 659*7c478bd9Sstevel@tonic-gate int rv; 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate PERFORM(_lockf(fildes, function, size)) 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) 665*7c478bd9Sstevel@tonic-gate int 666*7c478bd9Sstevel@tonic-gate lockf64(int fildes, int function, off64_t size) 667*7c478bd9Sstevel@tonic-gate { 668*7c478bd9Sstevel@tonic-gate extern int _lockf64(int, int, off64_t); 669*7c478bd9Sstevel@tonic-gate int rv; 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate PERFORM(_lockf64(fildes, function, size)) 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate ssize_t 676*7c478bd9Sstevel@tonic-gate msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 677*7c478bd9Sstevel@tonic-gate { 678*7c478bd9Sstevel@tonic-gate extern ssize_t _msgrcv(int, void *, size_t, long, int); 679*7c478bd9Sstevel@tonic-gate ssize_t rv; 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate PERFORM(_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate int 685*7c478bd9Sstevel@tonic-gate msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 686*7c478bd9Sstevel@tonic-gate { 687*7c478bd9Sstevel@tonic-gate extern int _msgsnd(int, const void *, size_t, int); 688*7c478bd9Sstevel@tonic-gate int rv; 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate PERFORM(_msgsnd(msqid, msgp, msgsz, msgflg)) 691*7c478bd9Sstevel@tonic-gate } 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate int 694*7c478bd9Sstevel@tonic-gate msync(caddr_t addr, size_t len, int flags) 695*7c478bd9Sstevel@tonic-gate { 696*7c478bd9Sstevel@tonic-gate extern int _msync(caddr_t, size_t, int); 697*7c478bd9Sstevel@tonic-gate int rv; 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate PERFORM(_msync(addr, len, flags)) 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate int 703*7c478bd9Sstevel@tonic-gate open(const char *path, int oflag, ...) 704*7c478bd9Sstevel@tonic-gate { 705*7c478bd9Sstevel@tonic-gate extern int _open(const char *, int, ...); 706*7c478bd9Sstevel@tonic-gate mode_t mode; 707*7c478bd9Sstevel@tonic-gate int rv; 708*7c478bd9Sstevel@tonic-gate va_list ap; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate va_start(ap, oflag); 711*7c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 712*7c478bd9Sstevel@tonic-gate va_end(ap); 713*7c478bd9Sstevel@tonic-gate PERFORM(_open(path, oflag, mode)) 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) 717*7c478bd9Sstevel@tonic-gate int 718*7c478bd9Sstevel@tonic-gate open64(const char *path, int oflag, ...) 719*7c478bd9Sstevel@tonic-gate { 720*7c478bd9Sstevel@tonic-gate extern int _open64(const char *, int, ...); 721*7c478bd9Sstevel@tonic-gate mode_t mode; 722*7c478bd9Sstevel@tonic-gate int rv; 723*7c478bd9Sstevel@tonic-gate va_list ap; 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate va_start(ap, oflag); 726*7c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 727*7c478bd9Sstevel@tonic-gate va_end(ap); 728*7c478bd9Sstevel@tonic-gate PERFORM(_open64(path, oflag, mode)) 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate int 733*7c478bd9Sstevel@tonic-gate pause(void) 734*7c478bd9Sstevel@tonic-gate { 735*7c478bd9Sstevel@tonic-gate extern int _pause(void); 736*7c478bd9Sstevel@tonic-gate int rv; 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate PERFORM(_pause()) 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate ssize_t 742*7c478bd9Sstevel@tonic-gate pread(int fildes, void *buf, size_t nbyte, off_t offset) 743*7c478bd9Sstevel@tonic-gate { 744*7c478bd9Sstevel@tonic-gate extern ssize_t _pread(int, void *, size_t, off_t); 745*7c478bd9Sstevel@tonic-gate ssize_t rv; 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate PERFORM(_pread(fildes, buf, nbyte, offset)) 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) 751*7c478bd9Sstevel@tonic-gate ssize_t 752*7c478bd9Sstevel@tonic-gate pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 753*7c478bd9Sstevel@tonic-gate { 754*7c478bd9Sstevel@tonic-gate extern ssize_t _pread64(int, void *, size_t, off64_t); 755*7c478bd9Sstevel@tonic-gate ssize_t rv; 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate PERFORM(_pread64(fildes, buf, nbyte, offset)) 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate ssize_t 762*7c478bd9Sstevel@tonic-gate pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 763*7c478bd9Sstevel@tonic-gate { 764*7c478bd9Sstevel@tonic-gate extern ssize_t _pwrite(int, const void *, size_t, off_t); 765*7c478bd9Sstevel@tonic-gate ssize_t rv; 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate PERFORM(_pwrite(fildes, buf, nbyte, offset)) 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) 771*7c478bd9Sstevel@tonic-gate ssize_t 772*7c478bd9Sstevel@tonic-gate pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 773*7c478bd9Sstevel@tonic-gate { 774*7c478bd9Sstevel@tonic-gate extern ssize_t _pwrite64(int, const void *, size_t, off64_t); 775*7c478bd9Sstevel@tonic-gate ssize_t rv; 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate PERFORM(_pwrite64(fildes, buf, nbyte, offset)) 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate ssize_t 782*7c478bd9Sstevel@tonic-gate readv(int fildes, const struct iovec *iov, int iovcnt) 783*7c478bd9Sstevel@tonic-gate { 784*7c478bd9Sstevel@tonic-gate extern ssize_t _readv(int, const struct iovec *, int); 785*7c478bd9Sstevel@tonic-gate ssize_t rv; 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate PERFORM(_readv(fildes, iov, iovcnt)) 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate int 791*7c478bd9Sstevel@tonic-gate sigpause(int sig) 792*7c478bd9Sstevel@tonic-gate { 793*7c478bd9Sstevel@tonic-gate extern int _sigpause(int); 794*7c478bd9Sstevel@tonic-gate int rv; 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate PERFORM(_sigpause(sig)) 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate #pragma weak sigsuspend = _sigsuspend 800*7c478bd9Sstevel@tonic-gate int 801*7c478bd9Sstevel@tonic-gate _sigsuspend(const sigset_t *set) 802*7c478bd9Sstevel@tonic-gate { 803*7c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 804*7c478bd9Sstevel@tonic-gate int rv; 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 807*7c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 808*7c478bd9Sstevel@tonic-gate EPILOGUE_MASK 809*7c478bd9Sstevel@tonic-gate return (rv); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate int 813*7c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 814*7c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 815*7c478bd9Sstevel@tonic-gate { 816*7c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 817*7c478bd9Sstevel@tonic-gate const sigset_t *); 818*7c478bd9Sstevel@tonic-gate int rv; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 821*7c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 822*7c478bd9Sstevel@tonic-gate EPILOGUE_MASK 823*7c478bd9Sstevel@tonic-gate return (rv); 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate int 827*7c478bd9Sstevel@tonic-gate __sigtimedwait(const sigset_t *set, siginfo_t *infop, 828*7c478bd9Sstevel@tonic-gate const timespec_t *timeout) 829*7c478bd9Sstevel@tonic-gate { 830*7c478bd9Sstevel@tonic-gate extern int ___sigtimedwait(const sigset_t *, siginfo_t *, 831*7c478bd9Sstevel@tonic-gate const timespec_t *); 832*7c478bd9Sstevel@tonic-gate siginfo_t info; 833*7c478bd9Sstevel@tonic-gate int sig; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate PROLOGUE 836*7c478bd9Sstevel@tonic-gate sig = ___sigtimedwait(set, &info, timeout); 837*7c478bd9Sstevel@tonic-gate if (sig == SIGCANCEL && 838*7c478bd9Sstevel@tonic-gate (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 839*7c478bd9Sstevel@tonic-gate do_sigcancel(); 840*7c478bd9Sstevel@tonic-gate errno = EINTR; 841*7c478bd9Sstevel@tonic-gate sig = -1; 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate EPILOGUE 844*7c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 845*7c478bd9Sstevel@tonic-gate *infop = info; 846*7c478bd9Sstevel@tonic-gate return (sig); 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate #pragma weak sigwait = _sigwait 850*7c478bd9Sstevel@tonic-gate int 851*7c478bd9Sstevel@tonic-gate _sigwait(sigset_t *set) 852*7c478bd9Sstevel@tonic-gate { 853*7c478bd9Sstevel@tonic-gate return (__sigtimedwait(set, NULL, NULL)); 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate int 857*7c478bd9Sstevel@tonic-gate tcdrain(int fildes) 858*7c478bd9Sstevel@tonic-gate { 859*7c478bd9Sstevel@tonic-gate extern int _tcdrain(int); 860*7c478bd9Sstevel@tonic-gate int rv; 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate PERFORM(_tcdrain(fildes)) 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate pid_t 866*7c478bd9Sstevel@tonic-gate wait(int *stat_loc) 867*7c478bd9Sstevel@tonic-gate { 868*7c478bd9Sstevel@tonic-gate extern pid_t _wait(int *); 869*7c478bd9Sstevel@tonic-gate pid_t rv; 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate PERFORM(_wait(stat_loc)) 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate pid_t 875*7c478bd9Sstevel@tonic-gate wait3(int *statusp, int options, struct rusage *rusage) 876*7c478bd9Sstevel@tonic-gate { 877*7c478bd9Sstevel@tonic-gate extern pid_t _wait3(int *, int, struct rusage *); 878*7c478bd9Sstevel@tonic-gate pid_t rv; 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate PERFORM(_wait3(statusp, options, rusage)) 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate int 884*7c478bd9Sstevel@tonic-gate waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 885*7c478bd9Sstevel@tonic-gate { 886*7c478bd9Sstevel@tonic-gate extern int _waitid(idtype_t, id_t, siginfo_t *, int); 887*7c478bd9Sstevel@tonic-gate int rv; 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate PERFORM(_waitid(idtype, id, infop, options)) 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate pid_t 893*7c478bd9Sstevel@tonic-gate waitpid(pid_t pid, int *stat_loc, int options) 894*7c478bd9Sstevel@tonic-gate { 895*7c478bd9Sstevel@tonic-gate extern pid_t _waitpid(pid_t, int *, int); 896*7c478bd9Sstevel@tonic-gate pid_t rv; 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate PERFORM(_waitpid(pid, stat_loc, options)) 899*7c478bd9Sstevel@tonic-gate } 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate ssize_t 902*7c478bd9Sstevel@tonic-gate writev(int fildes, const struct iovec *iov, int iovcnt) 903*7c478bd9Sstevel@tonic-gate { 904*7c478bd9Sstevel@tonic-gate extern ssize_t _writev(int, const struct iovec *, int); 905*7c478bd9Sstevel@tonic-gate ssize_t rv; 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate PERFORM(_writev(fildes, iov, iovcnt)) 908*7c478bd9Sstevel@tonic-gate } 909