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 /* 23e8031f0aSraf * Copyright 2006 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 /* 387c478bd9Sstevel@tonic-gate * fork_lock is special -- We can't use lmutex_lock() (and thereby enter 397c478bd9Sstevel@tonic-gate * a critical region) because the second thread to reach this point would 407c478bd9Sstevel@tonic-gate * become unstoppable and the first thread would hang waiting for the 417c478bd9Sstevel@tonic-gate * second thread to stop itself. Therefore we don't use lmutex_lock() in 427c478bd9Sstevel@tonic-gate * fork_lock_enter(), but we do defer signals (the other form of concurrency). 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * fork_lock_enter() does triple-duty. Not only does it serialize 457c478bd9Sstevel@tonic-gate * calls to fork() and forkall(), but it also serializes calls to 467c478bd9Sstevel@tonic-gate * thr_suspend() (fork() and forkall() also suspend other threads), 477c478bd9Sstevel@tonic-gate * and furthermore it serializes I18N calls to functions in other 487c478bd9Sstevel@tonic-gate * dlopen()ed L10N objects that might be calling malloc()/free(). 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static void 527c478bd9Sstevel@tonic-gate fork_lock_error(const char *who) 537c478bd9Sstevel@tonic-gate { 547c478bd9Sstevel@tonic-gate char msg[200]; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate (void) strlcpy(msg, "deadlock condition: ", sizeof (msg)); 577c478bd9Sstevel@tonic-gate (void) strlcat(msg, who, sizeof (msg)); 587c478bd9Sstevel@tonic-gate (void) strlcat(msg, "() called from a fork handler", sizeof (msg)); 597c478bd9Sstevel@tonic-gate thread_error(msg); 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate int 637c478bd9Sstevel@tonic-gate fork_lock_enter(const char *who) 647c478bd9Sstevel@tonic-gate { 657c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 667c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 677c478bd9Sstevel@tonic-gate int error = 0; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 707c478bd9Sstevel@tonic-gate sigoff(self); 717c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 727c478bd9Sstevel@tonic-gate while (udp->fork_count) { 737c478bd9Sstevel@tonic-gate if (udp->fork_owner == self) { 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * This is like a recursive lock except that we 767c478bd9Sstevel@tonic-gate * inform the caller if we have been called from 777c478bd9Sstevel@tonic-gate * a fork handler and let it deal with that fact. 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate if (self->ul_fork) { 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * We have been called from a fork handler. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate if (who != NULL && 847c478bd9Sstevel@tonic-gate udp->uberflags.uf_thread_error_detection) 857c478bd9Sstevel@tonic-gate fork_lock_error(who); 867c478bd9Sstevel@tonic-gate error = EDEADLK; 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate break; 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate ASSERT(self->ul_fork == 0); 917c478bd9Sstevel@tonic-gate (void) _cond_wait(&udp->fork_cond, &udp->fork_lock); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate udp->fork_owner = self; 947c478bd9Sstevel@tonic-gate udp->fork_count++; 957c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 967c478bd9Sstevel@tonic-gate return (error); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate void 1007c478bd9Sstevel@tonic-gate fork_lock_exit(void) 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1037c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 1067c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 1077c478bd9Sstevel@tonic-gate ASSERT(udp->fork_count != 0 && udp->fork_owner == self); 1087c478bd9Sstevel@tonic-gate if (--udp->fork_count == 0) { 1097c478bd9Sstevel@tonic-gate udp->fork_owner = NULL; 1107c478bd9Sstevel@tonic-gate (void) _cond_signal(&udp->fork_cond); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 1137c478bd9Sstevel@tonic-gate sigon(self); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 116*657b1f3dSraf #pragma weak forkx = _private_forkx 117*657b1f3dSraf #pragma weak _forkx = _private_forkx 118*657b1f3dSraf static pid_t 119*657b1f3dSraf _private_forkx(int flags) 1207c478bd9Sstevel@tonic-gate { 1217c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1227c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1237c478bd9Sstevel@tonic-gate pid_t pid; 1247c478bd9Sstevel@tonic-gate int error; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 1297c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 1307c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 1317c478bd9Sstevel@tonic-gate * must never call fork(). 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 1347c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1357c478bd9Sstevel@tonic-gate return (-1); 1367c478bd9Sstevel@tonic-gate } 137*657b1f3dSraf pid = __forkx(flags); 1387c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1397c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 1407c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate return (pid); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("fork")) != 0) { 1467c478bd9Sstevel@tonic-gate /* 1477c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate fork_lock_exit(); 1507c478bd9Sstevel@tonic-gate errno = error; 1517c478bd9Sstevel@tonic-gate return (-1); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate self->ul_fork = 1; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* 1567c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 1577c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 1587c478bd9Sstevel@tonic-gate * internal libc locks while invoking them. The fork_lock_enter() 1597c478bd9Sstevel@tonic-gate * function serializes fork(), thr_suspend(), pthread_atfork() and 1607c478bd9Sstevel@tonic-gate * dlclose() (which destroys whatever pthread_atfork() functions 1617c478bd9Sstevel@tonic-gate * the library may have set up). If one of these pthread_atfork() 1627c478bd9Sstevel@tonic-gate * functions attempts to fork or suspend another thread or call 1637c478bd9Sstevel@tonic-gate * pthread_atfork() or dlclose a library, it will detect a deadlock 1647c478bd9Sstevel@tonic-gate * in fork_lock_enter(). Otherwise, the pthread_atfork() functions 1657c478bd9Sstevel@tonic-gate * are free to do anything they please (except they will not 1667c478bd9Sstevel@tonic-gate * receive any signals). 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate _prefork_handler(); 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * Block all signals. 1727c478bd9Sstevel@tonic-gate * Just deferring them via sigon() is not enough. 1737c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 174*657b1f3dSraf * that was actually sent to the parent before __forkx(). 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate block_all_signals(self); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 1807c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 1817c478bd9Sstevel@tonic-gate * Thus, we are assured that no library locks are held 182*657b1f3dSraf * while we invoke fork() from the current thread. 1837c478bd9Sstevel@tonic-gate */ 1847c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 1857c478bd9Sstevel@tonic-gate suspend_fork(); 1867c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 1877c478bd9Sstevel@tonic-gate 188*657b1f3dSraf pid = __forkx(flags); 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 1937c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 194*657b1f3dSraf * Because we blocked all signals before __forkx(), a 1957c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 1987c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 1997c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2007c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2017c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2027c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 203f841f6adSraf postfork1_child(); 2047c478bd9Sstevel@tonic-gate restore_signals(self); 2057c478bd9Sstevel@tonic-gate _postfork_child_handler(); 2067c478bd9Sstevel@tonic-gate } else { 207*657b1f3dSraf /* restart all threads that were suspended for fork() */ 2087c478bd9Sstevel@tonic-gate continue_fork(0); 2097c478bd9Sstevel@tonic-gate restore_signals(self); 2107c478bd9Sstevel@tonic-gate _postfork_parent_handler(); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2147c478bd9Sstevel@tonic-gate fork_lock_exit(); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate return (pid); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 220*657b1f3dSraf * fork() is fork1() for both Posix threads and Solaris threads. 221*657b1f3dSraf * The forkall() interface exists for applications that require 222*657b1f3dSraf * the semantics of replicating all threads. 2237c478bd9Sstevel@tonic-gate */ 224*657b1f3dSraf #pragma weak fork1 = _fork 225*657b1f3dSraf #pragma weak _fork1 = _fork 226*657b1f3dSraf #pragma weak fork = _fork 2277c478bd9Sstevel@tonic-gate pid_t 228*657b1f3dSraf _fork(void) 229*657b1f3dSraf { 230*657b1f3dSraf return (_private_forkx(0)); 231*657b1f3dSraf } 232*657b1f3dSraf 233*657b1f3dSraf /* 234*657b1f3dSraf * Much of the logic here is the same as in forkx(). 235*657b1f3dSraf * See the comments in forkx(), above. 236*657b1f3dSraf */ 237*657b1f3dSraf #pragma weak forkallx = _private_forkallx 238*657b1f3dSraf #pragma weak _forkallx = _private_forkallx 239*657b1f3dSraf static pid_t 240*657b1f3dSraf _private_forkallx(int flags) 2417c478bd9Sstevel@tonic-gate { 2427c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 2437c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 2447c478bd9Sstevel@tonic-gate pid_t pid; 2457c478bd9Sstevel@tonic-gate int error; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 2487c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 2497c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2507c478bd9Sstevel@tonic-gate return (-1); 2517c478bd9Sstevel@tonic-gate } 252*657b1f3dSraf pid = __forkallx(flags); 2537c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2547c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2557c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate return (pid); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("forkall")) != 0) { 2617c478bd9Sstevel@tonic-gate fork_lock_exit(); 2627c478bd9Sstevel@tonic-gate errno = error; 2637c478bd9Sstevel@tonic-gate return (-1); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate self->ul_fork = 1; 2667c478bd9Sstevel@tonic-gate block_all_signals(self); 2677c478bd9Sstevel@tonic-gate suspend_fork(); 2687c478bd9Sstevel@tonic-gate 269*657b1f3dSraf pid = __forkallx(flags); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate if (pid == 0) { 2727c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2737c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2747c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2757c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2767c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2777c478bd9Sstevel@tonic-gate continue_fork(1); 2787c478bd9Sstevel@tonic-gate } else { 2797c478bd9Sstevel@tonic-gate continue_fork(0); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate restore_signals(self); 2827c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2837c478bd9Sstevel@tonic-gate fork_lock_exit(); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate return (pid); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 288*657b1f3dSraf #pragma weak forkall = _forkall 289*657b1f3dSraf pid_t 290*657b1f3dSraf _forkall(void) 291*657b1f3dSraf { 292*657b1f3dSraf return (_private_forkallx(0)); 293*657b1f3dSraf } 294*657b1f3dSraf 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Hacks for system calls to provide cancellation 2977c478bd9Sstevel@tonic-gate * and improve java garbage collection. 2987c478bd9Sstevel@tonic-gate */ 2997c478bd9Sstevel@tonic-gate #define PROLOGUE \ 3007c478bd9Sstevel@tonic-gate { \ 3017c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 3027c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 3037c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3047c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3057c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3067c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3077c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 3087c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED); \ 3097c478bd9Sstevel@tonic-gate } \ 3107c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate #define EPILOGUE \ 3147c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3157c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3167c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3177c478bd9Sstevel@tonic-gate } \ 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 3227c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 3237c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 3247c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 3257c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 3287c478bd9Sstevel@tonic-gate PROLOGUE \ 3297c478bd9Sstevel@tonic-gate if (nocancel) \ 3307c478bd9Sstevel@tonic-gate return (function_call); \ 3317c478bd9Sstevel@tonic-gate rv = function_call; \ 3327c478bd9Sstevel@tonic-gate EPILOGUE \ 3337c478bd9Sstevel@tonic-gate return (rv); 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 3377c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 3387c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 3397c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 3407c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 3417c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 3427c478bd9Sstevel@tonic-gate * for the particular signal. 3437c478bd9Sstevel@tonic-gate * 3447c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 3457c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 3467c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 3477c478bd9Sstevel@tonic-gate */ 3487c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 3497c478bd9Sstevel@tonic-gate { \ 3507c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 3517c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 3527c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 3537c478bd9Sstevel@tonic-gate if (sigmask) { \ 3547c478bd9Sstevel@tonic-gate block_all_signals(self); \ 3550293487cSraf self->ul_tmpmask.__sigbits[0] = sigmask->__sigbits[0]; \ 3560293487cSraf self->ul_tmpmask.__sigbits[1] = sigmask->__sigbits[1]; \ 3577c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 3587c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 3597c478bd9Sstevel@tonic-gate } \ 3607c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3617c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3627c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3637c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3647c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 3657c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3667c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 3677c478bd9Sstevel@tonic-gate restore_signals(self); \ 3687c478bd9Sstevel@tonic-gate } \ 3697c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED);\ 3707c478bd9Sstevel@tonic-gate } \ 3717c478bd9Sstevel@tonic-gate } \ 3727c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 3737c478bd9Sstevel@tonic-gate } \ 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 3787c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 3797c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 3807c478bd9Sstevel@tonic-gate * original signal mask ourself. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 3837c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3847c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3857c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3867c478bd9Sstevel@tonic-gate } \ 3877c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3887c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 3897c478bd9Sstevel@tonic-gate restore_signals(self); \ 3907c478bd9Sstevel@tonic-gate } \ 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 39334709573Sraf /* 394f841f6adSraf * Cancellation prologue and epilogue functions, 395f841f6adSraf * for cancellation points too complex to include here. 39634709573Sraf */ 39734709573Sraf void 39834709573Sraf _cancel_prologue(void) 39934709573Sraf { 40034709573Sraf ulwp_t *self = curthread; 40134709573Sraf 40234709573Sraf self->ul_cancel_prologue = (self->ul_vfork | self->ul_nocancel); 40334709573Sraf if (self->ul_cancel_prologue == 0) { 40434709573Sraf self->ul_save_async = self->ul_cancel_async; 40534709573Sraf if (!self->ul_cancel_disabled) { 40634709573Sraf self->ul_cancel_async = 1; 40734709573Sraf if (self->ul_cancel_pending) 40834709573Sraf _pthread_exit(PTHREAD_CANCELED); 40934709573Sraf } 41034709573Sraf self->ul_sp = stkptr(); 41134709573Sraf } 41234709573Sraf } 41334709573Sraf 41434709573Sraf void 41534709573Sraf _cancel_epilogue(void) 41634709573Sraf { 41734709573Sraf ulwp_t *self = curthread; 41834709573Sraf 41934709573Sraf if (self->ul_cancel_prologue == 0) { 42034709573Sraf self->ul_sp = 0; 42134709573Sraf self->ul_cancel_async = self->ul_save_async; 42234709573Sraf } 42334709573Sraf } 42434709573Sraf 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate int 4297c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 4307c478bd9Sstevel@tonic-gate { 4317c478bd9Sstevel@tonic-gate int error; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate PROLOGUE 4347c478bd9Sstevel@tonic-gate while ((error = __lwp_wait(tid, found)) == EINTR) 4357c478bd9Sstevel@tonic-gate ; 4367c478bd9Sstevel@tonic-gate EPILOGUE 4377c478bd9Sstevel@tonic-gate return (error); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate ssize_t 4417c478bd9Sstevel@tonic-gate read(int fd, void *buf, size_t size) 4427c478bd9Sstevel@tonic-gate { 4437c478bd9Sstevel@tonic-gate extern ssize_t _read(int, void *, size_t); 4447c478bd9Sstevel@tonic-gate ssize_t rv; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate PERFORM(_read(fd, buf, size)) 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate ssize_t 4507c478bd9Sstevel@tonic-gate write(int fd, const void *buf, size_t size) 4517c478bd9Sstevel@tonic-gate { 4527c478bd9Sstevel@tonic-gate extern ssize_t _write(int, const void *, size_t); 4537c478bd9Sstevel@tonic-gate ssize_t rv; 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate PERFORM(_write(fd, buf, size)) 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate int 4597c478bd9Sstevel@tonic-gate getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4607c478bd9Sstevel@tonic-gate int *flagsp) 4617c478bd9Sstevel@tonic-gate { 4627c478bd9Sstevel@tonic-gate extern int _getmsg(int, struct strbuf *, struct strbuf *, int *); 4637c478bd9Sstevel@tonic-gate int rv; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate PERFORM(_getmsg(fd, ctlptr, dataptr, flagsp)) 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate int 4697c478bd9Sstevel@tonic-gate getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4707c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate extern int _getpmsg(int, struct strbuf *, struct strbuf *, 4737c478bd9Sstevel@tonic-gate int *, int *); 4747c478bd9Sstevel@tonic-gate int rv; 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate PERFORM(_getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate int 4807c478bd9Sstevel@tonic-gate putmsg(int fd, const struct strbuf *ctlptr, 4817c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4827c478bd9Sstevel@tonic-gate { 4837c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 4847c478bd9Sstevel@tonic-gate const struct strbuf *, int); 4857c478bd9Sstevel@tonic-gate int rv; 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags)) 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate int 4917c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 4927c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4937c478bd9Sstevel@tonic-gate { 4947c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 4957c478bd9Sstevel@tonic-gate const struct strbuf *, int); 4967c478bd9Sstevel@tonic-gate int rv; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate int 5027c478bd9Sstevel@tonic-gate putpmsg(int fd, const struct strbuf *ctlptr, 5037c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5047c478bd9Sstevel@tonic-gate { 5057c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 5067c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 5077c478bd9Sstevel@tonic-gate int rv; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags)) 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate int 5137c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 5147c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5157c478bd9Sstevel@tonic-gate { 5167c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 5177c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 5187c478bd9Sstevel@tonic-gate int rv; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 523f841f6adSraf #pragma weak nanosleep = _nanosleep 5247c478bd9Sstevel@tonic-gate int 525f841f6adSraf _nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 5267c478bd9Sstevel@tonic-gate { 5277c478bd9Sstevel@tonic-gate int error; 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate PROLOGUE 530f841f6adSraf error = __nanosleep(rqtp, rmtp); 5317c478bd9Sstevel@tonic-gate EPILOGUE 5327c478bd9Sstevel@tonic-gate if (error) { 5337c478bd9Sstevel@tonic-gate errno = error; 5347c478bd9Sstevel@tonic-gate return (-1); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate return (0); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 539f841f6adSraf #pragma weak clock_nanosleep = _clock_nanosleep 5407c478bd9Sstevel@tonic-gate int 541f841f6adSraf _clock_nanosleep(clockid_t clock_id, int flags, 5427c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 5437c478bd9Sstevel@tonic-gate { 5447c478bd9Sstevel@tonic-gate timespec_t reltime; 5457c478bd9Sstevel@tonic-gate hrtime_t start; 5467c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 5477c478bd9Sstevel@tonic-gate hrtime_t lapse; 5487c478bd9Sstevel@tonic-gate int error; 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate switch (clock_id) { 5517c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 5527c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 5537c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 5547c478bd9Sstevel@tonic-gate return (ENOTSUP); 5557c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 5567c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 5577c478bd9Sstevel@tonic-gate break; 5587c478bd9Sstevel@tonic-gate default: 5597c478bd9Sstevel@tonic-gate return (EINVAL); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5627c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5637c478bd9Sstevel@tonic-gate rmtp = NULL; 5647c478bd9Sstevel@tonic-gate } else { 5657c478bd9Sstevel@tonic-gate reltime = *rqtp; 5667c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 5677c478bd9Sstevel@tonic-gate start = gethrtime(); 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate restart: 5707c478bd9Sstevel@tonic-gate PROLOGUE 571f841f6adSraf error = __nanosleep(&reltime, rmtp); 5727c478bd9Sstevel@tonic-gate EPILOGUE 5737c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 5767c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 5777c478bd9Sstevel@tonic-gate * the system clock. 5787c478bd9Sstevel@tonic-gate */ 5797c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5807c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 5817c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 5827c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5837c478bd9Sstevel@tonic-gate goto restart; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate } else { 5867c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 5877c478bd9Sstevel@tonic-gate rqtp->tv_nsec; 5887c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 5897c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 5907c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 5917c478bd9Sstevel@tonic-gate goto restart; 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 5967c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 5977c478bd9Sstevel@tonic-gate /* 5987c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 5997c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 6007c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 6017c478bd9Sstevel@tonic-gate * 6027c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 6037c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 6047c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 6057c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 6067c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 6077c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 6087c478bd9Sstevel@tonic-gate */ 6097c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6107c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 6117c478bd9Sstevel@tonic-gate goto restart; 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate return (error); 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate #pragma weak sleep = _sleep 6177c478bd9Sstevel@tonic-gate unsigned int 6187c478bd9Sstevel@tonic-gate _sleep(unsigned int sec) 6197c478bd9Sstevel@tonic-gate { 6207c478bd9Sstevel@tonic-gate unsigned int rem = 0; 6217c478bd9Sstevel@tonic-gate int error; 6227c478bd9Sstevel@tonic-gate timespec_t ts; 6237c478bd9Sstevel@tonic-gate timespec_t tsr; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 6267c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 6277c478bd9Sstevel@tonic-gate PROLOGUE 628f841f6adSraf error = __nanosleep(&ts, &tsr); 6297c478bd9Sstevel@tonic-gate EPILOGUE 6307c478bd9Sstevel@tonic-gate if (error == EINTR) { 6317c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 6327c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 6337c478bd9Sstevel@tonic-gate rem++; 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate return (rem); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate #pragma weak usleep = _usleep 6397c478bd9Sstevel@tonic-gate int 6407c478bd9Sstevel@tonic-gate _usleep(useconds_t usec) 6417c478bd9Sstevel@tonic-gate { 6427c478bd9Sstevel@tonic-gate timespec_t ts; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 6457c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 6467c478bd9Sstevel@tonic-gate PROLOGUE 647f841f6adSraf (void) __nanosleep(&ts, NULL); 6487c478bd9Sstevel@tonic-gate EPILOGUE 6497c478bd9Sstevel@tonic-gate return (0); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate int 6537c478bd9Sstevel@tonic-gate close(int fildes) 6547c478bd9Sstevel@tonic-gate { 655f841f6adSraf extern void _aio_close(int); 6567c478bd9Sstevel@tonic-gate extern int _close(int); 6577c478bd9Sstevel@tonic-gate int rv; 6587c478bd9Sstevel@tonic-gate 659f841f6adSraf _aio_close(fildes); 6607c478bd9Sstevel@tonic-gate PERFORM(_close(fildes)) 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate int 6647c478bd9Sstevel@tonic-gate creat(const char *path, mode_t mode) 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate extern int _creat(const char *, mode_t); 6677c478bd9Sstevel@tonic-gate int rv; 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate PERFORM(_creat(path, mode)) 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate #if !defined(_LP64) 6737c478bd9Sstevel@tonic-gate int 6747c478bd9Sstevel@tonic-gate creat64(const char *path, mode_t mode) 6757c478bd9Sstevel@tonic-gate { 6767c478bd9Sstevel@tonic-gate extern int _creat64(const char *, mode_t); 6777c478bd9Sstevel@tonic-gate int rv; 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate PERFORM(_creat64(path, mode)) 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate int 6847c478bd9Sstevel@tonic-gate fcntl(int fildes, int cmd, ...) 6857c478bd9Sstevel@tonic-gate { 6867c478bd9Sstevel@tonic-gate extern int _fcntl(int, int, ...); 6877c478bd9Sstevel@tonic-gate intptr_t arg; 6887c478bd9Sstevel@tonic-gate int rv; 6897c478bd9Sstevel@tonic-gate va_list ap; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate va_start(ap, cmd); 6927c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 6937c478bd9Sstevel@tonic-gate va_end(ap); 6947c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 6957c478bd9Sstevel@tonic-gate return (_fcntl(fildes, cmd, arg)); 6967c478bd9Sstevel@tonic-gate PERFORM(_fcntl(fildes, cmd, arg)) 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate int 7007c478bd9Sstevel@tonic-gate fsync(int fildes) 7017c478bd9Sstevel@tonic-gate { 7027c478bd9Sstevel@tonic-gate extern int _fsync(int); 7037c478bd9Sstevel@tonic-gate int rv; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate PERFORM(_fsync(fildes)) 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate int 7097c478bd9Sstevel@tonic-gate lockf(int fildes, int function, off_t size) 7107c478bd9Sstevel@tonic-gate { 7117c478bd9Sstevel@tonic-gate extern int _lockf(int, int, off_t); 7127c478bd9Sstevel@tonic-gate int rv; 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate PERFORM(_lockf(fildes, function, size)) 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7187c478bd9Sstevel@tonic-gate int 7197c478bd9Sstevel@tonic-gate lockf64(int fildes, int function, off64_t size) 7207c478bd9Sstevel@tonic-gate { 7217c478bd9Sstevel@tonic-gate extern int _lockf64(int, int, off64_t); 7227c478bd9Sstevel@tonic-gate int rv; 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate PERFORM(_lockf64(fildes, function, size)) 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate ssize_t 7297c478bd9Sstevel@tonic-gate msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 7307c478bd9Sstevel@tonic-gate { 7317c478bd9Sstevel@tonic-gate extern ssize_t _msgrcv(int, void *, size_t, long, int); 7327c478bd9Sstevel@tonic-gate ssize_t rv; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate PERFORM(_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate int 7387c478bd9Sstevel@tonic-gate msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate extern int _msgsnd(int, const void *, size_t, int); 7417c478bd9Sstevel@tonic-gate int rv; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate PERFORM(_msgsnd(msqid, msgp, msgsz, msgflg)) 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate int 7477c478bd9Sstevel@tonic-gate msync(caddr_t addr, size_t len, int flags) 7487c478bd9Sstevel@tonic-gate { 7497c478bd9Sstevel@tonic-gate extern int _msync(caddr_t, size_t, int); 7507c478bd9Sstevel@tonic-gate int rv; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate PERFORM(_msync(addr, len, flags)) 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate int 7567c478bd9Sstevel@tonic-gate open(const char *path, int oflag, ...) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate extern int _open(const char *, int, ...); 7597c478bd9Sstevel@tonic-gate mode_t mode; 7607c478bd9Sstevel@tonic-gate int rv; 7617c478bd9Sstevel@tonic-gate va_list ap; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7647c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7657c478bd9Sstevel@tonic-gate va_end(ap); 7667c478bd9Sstevel@tonic-gate PERFORM(_open(path, oflag, mode)) 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7707c478bd9Sstevel@tonic-gate int 7717c478bd9Sstevel@tonic-gate open64(const char *path, int oflag, ...) 7727c478bd9Sstevel@tonic-gate { 7737c478bd9Sstevel@tonic-gate extern int _open64(const char *, int, ...); 7747c478bd9Sstevel@tonic-gate mode_t mode; 7757c478bd9Sstevel@tonic-gate int rv; 7767c478bd9Sstevel@tonic-gate va_list ap; 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7797c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7807c478bd9Sstevel@tonic-gate va_end(ap); 7817c478bd9Sstevel@tonic-gate PERFORM(_open64(path, oflag, mode)) 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate int 7867c478bd9Sstevel@tonic-gate pause(void) 7877c478bd9Sstevel@tonic-gate { 7887c478bd9Sstevel@tonic-gate extern int _pause(void); 7897c478bd9Sstevel@tonic-gate int rv; 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate PERFORM(_pause()) 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate ssize_t 7957c478bd9Sstevel@tonic-gate pread(int fildes, void *buf, size_t nbyte, off_t offset) 7967c478bd9Sstevel@tonic-gate { 7977c478bd9Sstevel@tonic-gate extern ssize_t _pread(int, void *, size_t, off_t); 7987c478bd9Sstevel@tonic-gate ssize_t rv; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate PERFORM(_pread(fildes, buf, nbyte, offset)) 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate #if !defined(_LP64) 8047c478bd9Sstevel@tonic-gate ssize_t 8057c478bd9Sstevel@tonic-gate pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate extern ssize_t _pread64(int, void *, size_t, off64_t); 8087c478bd9Sstevel@tonic-gate ssize_t rv; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate PERFORM(_pread64(fildes, buf, nbyte, offset)) 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate ssize_t 8157c478bd9Sstevel@tonic-gate pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 8167c478bd9Sstevel@tonic-gate { 8177c478bd9Sstevel@tonic-gate extern ssize_t _pwrite(int, const void *, size_t, off_t); 8187c478bd9Sstevel@tonic-gate ssize_t rv; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate PERFORM(_pwrite(fildes, buf, nbyte, offset)) 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate #if !defined(_LP64) 8247c478bd9Sstevel@tonic-gate ssize_t 8257c478bd9Sstevel@tonic-gate pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 8267c478bd9Sstevel@tonic-gate { 8277c478bd9Sstevel@tonic-gate extern ssize_t _pwrite64(int, const void *, size_t, off64_t); 8287c478bd9Sstevel@tonic-gate ssize_t rv; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate PERFORM(_pwrite64(fildes, buf, nbyte, offset)) 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate ssize_t 8357c478bd9Sstevel@tonic-gate readv(int fildes, const struct iovec *iov, int iovcnt) 8367c478bd9Sstevel@tonic-gate { 8377c478bd9Sstevel@tonic-gate extern ssize_t _readv(int, const struct iovec *, int); 8387c478bd9Sstevel@tonic-gate ssize_t rv; 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate PERFORM(_readv(fildes, iov, iovcnt)) 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate int 8447c478bd9Sstevel@tonic-gate sigpause(int sig) 8457c478bd9Sstevel@tonic-gate { 8467c478bd9Sstevel@tonic-gate extern int _sigpause(int); 8477c478bd9Sstevel@tonic-gate int rv; 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate PERFORM(_sigpause(sig)) 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate #pragma weak sigsuspend = _sigsuspend 8537c478bd9Sstevel@tonic-gate int 8547c478bd9Sstevel@tonic-gate _sigsuspend(const sigset_t *set) 8557c478bd9Sstevel@tonic-gate { 8567c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 8577c478bd9Sstevel@tonic-gate int rv; 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 8607c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 8617c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8627c478bd9Sstevel@tonic-gate return (rv); 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate int 8667c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 8677c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 8687c478bd9Sstevel@tonic-gate { 8697c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 8707c478bd9Sstevel@tonic-gate const sigset_t *); 8717c478bd9Sstevel@tonic-gate int rv; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 8747c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 8757c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8767c478bd9Sstevel@tonic-gate return (rv); 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate 879f841f6adSraf #pragma weak sigtimedwait = _sigtimedwait 8807c478bd9Sstevel@tonic-gate int 881f841f6adSraf _sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout) 8827c478bd9Sstevel@tonic-gate { 883f841f6adSraf extern int __sigtimedwait(const sigset_t *, siginfo_t *, 8847c478bd9Sstevel@tonic-gate const timespec_t *); 8857c478bd9Sstevel@tonic-gate siginfo_t info; 8867c478bd9Sstevel@tonic-gate int sig; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate PROLOGUE 889f841f6adSraf sig = __sigtimedwait(set, &info, timeout); 8907c478bd9Sstevel@tonic-gate if (sig == SIGCANCEL && 8917c478bd9Sstevel@tonic-gate (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 8927c478bd9Sstevel@tonic-gate do_sigcancel(); 8937c478bd9Sstevel@tonic-gate errno = EINTR; 8947c478bd9Sstevel@tonic-gate sig = -1; 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate EPILOGUE 8977c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 8980293487cSraf (void) _private_memcpy(infop, &info, sizeof (*infop)); 8997c478bd9Sstevel@tonic-gate return (sig); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate #pragma weak sigwait = _sigwait 9037c478bd9Sstevel@tonic-gate int 9047c478bd9Sstevel@tonic-gate _sigwait(sigset_t *set) 9057c478bd9Sstevel@tonic-gate { 906f841f6adSraf return (_sigtimedwait(set, NULL, NULL)); 907f841f6adSraf } 908f841f6adSraf 909f841f6adSraf #pragma weak sigwaitinfo = _sigwaitinfo 910f841f6adSraf int 911f841f6adSraf _sigwaitinfo(const sigset_t *set, siginfo_t *info) 912f841f6adSraf { 913f841f6adSraf return (_sigtimedwait(set, info, NULL)); 914f841f6adSraf } 915f841f6adSraf 916f841f6adSraf #pragma weak sigqueue = _sigqueue 917f841f6adSraf int 918f841f6adSraf _sigqueue(pid_t pid, int signo, const union sigval value) 919f841f6adSraf { 920f841f6adSraf extern int __sigqueue(pid_t pid, int signo, 921f841f6adSraf /* const union sigval */ void *value, int si_code, int block); 922f841f6adSraf return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0)); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate int 9267c478bd9Sstevel@tonic-gate tcdrain(int fildes) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate extern int _tcdrain(int); 9297c478bd9Sstevel@tonic-gate int rv; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate PERFORM(_tcdrain(fildes)) 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate pid_t 9357c478bd9Sstevel@tonic-gate wait(int *stat_loc) 9367c478bd9Sstevel@tonic-gate { 9377c478bd9Sstevel@tonic-gate extern pid_t _wait(int *); 9387c478bd9Sstevel@tonic-gate pid_t rv; 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate PERFORM(_wait(stat_loc)) 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate pid_t 9447c478bd9Sstevel@tonic-gate wait3(int *statusp, int options, struct rusage *rusage) 9457c478bd9Sstevel@tonic-gate { 9467c478bd9Sstevel@tonic-gate extern pid_t _wait3(int *, int, struct rusage *); 9477c478bd9Sstevel@tonic-gate pid_t rv; 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate PERFORM(_wait3(statusp, options, rusage)) 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate int 9537c478bd9Sstevel@tonic-gate waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 9547c478bd9Sstevel@tonic-gate { 9557c478bd9Sstevel@tonic-gate extern int _waitid(idtype_t, id_t, siginfo_t *, int); 9567c478bd9Sstevel@tonic-gate int rv; 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate PERFORM(_waitid(idtype, id, infop, options)) 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 961e8031f0aSraf /* 962e8031f0aSraf * waitpid_cancel() is a libc-private symbol for internal use 963e8031f0aSraf * where cancellation semantics is desired (see system()). 964e8031f0aSraf */ 965e8031f0aSraf #pragma weak waitpid_cancel = waitpid 9667c478bd9Sstevel@tonic-gate pid_t 9677c478bd9Sstevel@tonic-gate waitpid(pid_t pid, int *stat_loc, int options) 9687c478bd9Sstevel@tonic-gate { 9697c478bd9Sstevel@tonic-gate extern pid_t _waitpid(pid_t, int *, int); 9707c478bd9Sstevel@tonic-gate pid_t rv; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate PERFORM(_waitpid(pid, stat_loc, options)) 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate ssize_t 9767c478bd9Sstevel@tonic-gate writev(int fildes, const struct iovec *iov, int iovcnt) 9777c478bd9Sstevel@tonic-gate { 9787c478bd9Sstevel@tonic-gate extern ssize_t _writev(int, const struct iovec *, int); 9797c478bd9Sstevel@tonic-gate ssize_t rv; 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate PERFORM(_writev(fildes, iov, iovcnt)) 9827c478bd9Sstevel@tonic-gate } 983