17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 534709573Sraf * Common Development and Distribution License (the "License"). 634709573Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 210293487cSraf 227c478bd9Sstevel@tonic-gate /* 2336319254Sraf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include "lint.h" 307c478bd9Sstevel@tonic-gate #include "thr_uberdata.h" 317c478bd9Sstevel@tonic-gate #include <stdarg.h> 327c478bd9Sstevel@tonic-gate #include <poll.h> 337c478bd9Sstevel@tonic-gate #include <stropts.h> 347c478bd9Sstevel@tonic-gate #include <dlfcn.h> 357c478bd9Sstevel@tonic-gate #include <sys/uio.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* 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); 7236319254Sraf if (udp->fork_count) { 7336319254Sraf ASSERT(udp->fork_owner == self); 7436319254Sraf /* 7536319254Sraf * This is a simple recursive lock except that we 7636319254Sraf * inform the caller if we have been called from 7736319254Sraf * a fork handler and let it deal with that fact. 7836319254Sraf */ 7936319254Sraf if (self->ul_fork) { 807c478bd9Sstevel@tonic-gate /* 8136319254Sraf * We have been called from a fork handler. 827c478bd9Sstevel@tonic-gate */ 8336319254Sraf if (who != NULL && 8436319254Sraf udp->uberflags.uf_thread_error_detection) 8536319254Sraf fork_lock_error(who); 8636319254Sraf error = EDEADLK; 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate udp->fork_owner = self; 907c478bd9Sstevel@tonic-gate udp->fork_count++; 917c478bd9Sstevel@tonic-gate return (error); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate void 957c478bd9Sstevel@tonic-gate fork_lock_exit(void) 967c478bd9Sstevel@tonic-gate { 977c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 987c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 1017c478bd9Sstevel@tonic-gate ASSERT(udp->fork_count != 0 && udp->fork_owner == self); 10236319254Sraf if (--udp->fork_count == 0) 1037c478bd9Sstevel@tonic-gate udp->fork_owner = NULL; 1047c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 1057c478bd9Sstevel@tonic-gate sigon(self); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 108dfb96a4fSab /* 109dfb96a4fSab * Note: Instead of making this function static, we reduce it to local 110dfb96a4fSab * scope in the mapfile. That allows the linker to prevent it from 111dfb96a4fSab * appearing in the .SUNW_dynsymsort section. 112dfb96a4fSab */ 113657b1f3dSraf #pragma weak forkx = _private_forkx 114657b1f3dSraf #pragma weak _forkx = _private_forkx 115dfb96a4fSab pid_t 116657b1f3dSraf _private_forkx(int flags) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1197c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1207c478bd9Sstevel@tonic-gate pid_t pid; 1217c478bd9Sstevel@tonic-gate int error; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 1267c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 1277c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 1287c478bd9Sstevel@tonic-gate * must never call fork(). 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 1317c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1327c478bd9Sstevel@tonic-gate return (-1); 1337c478bd9Sstevel@tonic-gate } 134657b1f3dSraf pid = __forkx(flags); 1357c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1367c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 1377c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate return (pid); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("fork")) != 0) { 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate fork_lock_exit(); 1477c478bd9Sstevel@tonic-gate errno = error; 1487c478bd9Sstevel@tonic-gate return (-1); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate self->ul_fork = 1; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 1547c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 1557c478bd9Sstevel@tonic-gate * internal libc locks while invoking them. The fork_lock_enter() 1567c478bd9Sstevel@tonic-gate * function serializes fork(), thr_suspend(), pthread_atfork() and 1577c478bd9Sstevel@tonic-gate * dlclose() (which destroys whatever pthread_atfork() functions 1587c478bd9Sstevel@tonic-gate * the library may have set up). If one of these pthread_atfork() 1597c478bd9Sstevel@tonic-gate * functions attempts to fork or suspend another thread or call 1607c478bd9Sstevel@tonic-gate * pthread_atfork() or dlclose a library, it will detect a deadlock 1617c478bd9Sstevel@tonic-gate * in fork_lock_enter(). Otherwise, the pthread_atfork() functions 1627c478bd9Sstevel@tonic-gate * are free to do anything they please (except they will not 1637c478bd9Sstevel@tonic-gate * receive any signals). 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate _prefork_handler(); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * Block all signals. 1697c478bd9Sstevel@tonic-gate * Just deferring them via sigon() is not enough. 1707c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 171657b1f3dSraf * that was actually sent to the parent before __forkx(). 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate block_all_signals(self); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 1777c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 1787c478bd9Sstevel@tonic-gate * Thus, we are assured that no library locks are held 179657b1f3dSraf * while we invoke fork() from the current thread. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate suspend_fork(); 1827c478bd9Sstevel@tonic-gate 183657b1f3dSraf pid = __forkx(flags); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 1887c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 189657b1f3dSraf * Because we blocked all signals before __forkx(), a 1907c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 1937c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 1947c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 1957c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 1967c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 1977c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 198883492d5Sraf unregister_locks(); 199f841f6adSraf postfork1_child(); 2007c478bd9Sstevel@tonic-gate restore_signals(self); 2017c478bd9Sstevel@tonic-gate _postfork_child_handler(); 2027c478bd9Sstevel@tonic-gate } else { 203657b1f3dSraf /* restart all threads that were suspended for fork() */ 2047c478bd9Sstevel@tonic-gate continue_fork(0); 2057c478bd9Sstevel@tonic-gate restore_signals(self); 2067c478bd9Sstevel@tonic-gate _postfork_parent_handler(); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2107c478bd9Sstevel@tonic-gate fork_lock_exit(); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate return (pid); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 216657b1f3dSraf * fork() is fork1() for both Posix threads and Solaris threads. 217657b1f3dSraf * The forkall() interface exists for applications that require 218657b1f3dSraf * the semantics of replicating all threads. 2197c478bd9Sstevel@tonic-gate */ 220657b1f3dSraf #pragma weak fork1 = _fork 221657b1f3dSraf #pragma weak _fork1 = _fork 222657b1f3dSraf #pragma weak fork = _fork 2237c478bd9Sstevel@tonic-gate pid_t 224657b1f3dSraf _fork(void) 225657b1f3dSraf { 226657b1f3dSraf return (_private_forkx(0)); 227657b1f3dSraf } 228657b1f3dSraf 229657b1f3dSraf /* 230657b1f3dSraf * Much of the logic here is the same as in forkx(). 231657b1f3dSraf * See the comments in forkx(), above. 232657b1f3dSraf */ 233657b1f3dSraf #pragma weak forkallx = _private_forkallx 234657b1f3dSraf #pragma weak _forkallx = _private_forkallx 235dfb96a4fSab pid_t 236657b1f3dSraf _private_forkallx(int flags) 2377c478bd9Sstevel@tonic-gate { 2387c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 2397c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 2407c478bd9Sstevel@tonic-gate pid_t pid; 2417c478bd9Sstevel@tonic-gate int error; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 2447c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 2457c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2467c478bd9Sstevel@tonic-gate return (-1); 2477c478bd9Sstevel@tonic-gate } 248657b1f3dSraf pid = __forkallx(flags); 2497c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2507c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2517c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate return (pid); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("forkall")) != 0) { 2577c478bd9Sstevel@tonic-gate fork_lock_exit(); 2587c478bd9Sstevel@tonic-gate errno = error; 2597c478bd9Sstevel@tonic-gate return (-1); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate self->ul_fork = 1; 2627c478bd9Sstevel@tonic-gate block_all_signals(self); 2637c478bd9Sstevel@tonic-gate suspend_fork(); 2647c478bd9Sstevel@tonic-gate 265657b1f3dSraf pid = __forkallx(flags); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate if (pid == 0) { 2687c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2697c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2707c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2717c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2727c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 273883492d5Sraf unregister_locks(); 2747c478bd9Sstevel@tonic-gate continue_fork(1); 2757c478bd9Sstevel@tonic-gate } else { 2767c478bd9Sstevel@tonic-gate continue_fork(0); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate restore_signals(self); 2797c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2807c478bd9Sstevel@tonic-gate fork_lock_exit(); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate return (pid); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 285657b1f3dSraf #pragma weak forkall = _forkall 286657b1f3dSraf pid_t 287657b1f3dSraf _forkall(void) 288657b1f3dSraf { 289657b1f3dSraf return (_private_forkallx(0)); 290657b1f3dSraf } 291657b1f3dSraf 2927c478bd9Sstevel@tonic-gate /* 2937c478bd9Sstevel@tonic-gate * Hacks for system calls to provide cancellation 2947c478bd9Sstevel@tonic-gate * and improve java garbage collection. 2957c478bd9Sstevel@tonic-gate */ 2967c478bd9Sstevel@tonic-gate #define PROLOGUE \ 2977c478bd9Sstevel@tonic-gate { \ 2987c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 2997c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 3007c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3017c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3027c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3037c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3047c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 3057c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED); \ 3067c478bd9Sstevel@tonic-gate } \ 3077c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate #define EPILOGUE \ 3117c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3127c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3137c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3147c478bd9Sstevel@tonic-gate } \ 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 3197c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 3207c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 3217c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 3227c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 3257c478bd9Sstevel@tonic-gate PROLOGUE \ 3267c478bd9Sstevel@tonic-gate if (nocancel) \ 3277c478bd9Sstevel@tonic-gate return (function_call); \ 3287c478bd9Sstevel@tonic-gate rv = function_call; \ 3297c478bd9Sstevel@tonic-gate EPILOGUE \ 3307c478bd9Sstevel@tonic-gate return (rv); 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 3347c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 3357c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 3367c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 3377c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 3387c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 3397c478bd9Sstevel@tonic-gate * for the particular signal. 3407c478bd9Sstevel@tonic-gate * 3417c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 3427c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 3437c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 3447c478bd9Sstevel@tonic-gate */ 3457c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 3467c478bd9Sstevel@tonic-gate { \ 3477c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 3487c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 3497c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 3507c478bd9Sstevel@tonic-gate if (sigmask) { \ 3517c478bd9Sstevel@tonic-gate block_all_signals(self); \ 3520293487cSraf self->ul_tmpmask.__sigbits[0] = sigmask->__sigbits[0]; \ 3530293487cSraf self->ul_tmpmask.__sigbits[1] = sigmask->__sigbits[1]; \ 3547c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 3557c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 3567c478bd9Sstevel@tonic-gate } \ 3577c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3587c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3597c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3607c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3617c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 3627c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3637c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 3647c478bd9Sstevel@tonic-gate restore_signals(self); \ 3657c478bd9Sstevel@tonic-gate } \ 3667c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED);\ 3677c478bd9Sstevel@tonic-gate } \ 3687c478bd9Sstevel@tonic-gate } \ 3697c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 3707c478bd9Sstevel@tonic-gate } \ 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* 3747c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 3757c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 3767c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 3777c478bd9Sstevel@tonic-gate * original signal mask ourself. 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 3807c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3817c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3827c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3837c478bd9Sstevel@tonic-gate } \ 3847c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3857c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 3867c478bd9Sstevel@tonic-gate restore_signals(self); \ 3877c478bd9Sstevel@tonic-gate } \ 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 39034709573Sraf /* 391f841f6adSraf * Cancellation prologue and epilogue functions, 392f841f6adSraf * for cancellation points too complex to include here. 39334709573Sraf */ 39434709573Sraf void 39534709573Sraf _cancel_prologue(void) 39634709573Sraf { 39734709573Sraf ulwp_t *self = curthread; 39834709573Sraf 39934709573Sraf self->ul_cancel_prologue = (self->ul_vfork | self->ul_nocancel); 40034709573Sraf if (self->ul_cancel_prologue == 0) { 40134709573Sraf self->ul_save_async = self->ul_cancel_async; 40234709573Sraf if (!self->ul_cancel_disabled) { 40334709573Sraf self->ul_cancel_async = 1; 40434709573Sraf if (self->ul_cancel_pending) 40534709573Sraf _pthread_exit(PTHREAD_CANCELED); 40634709573Sraf } 40734709573Sraf self->ul_sp = stkptr(); 40834709573Sraf } 40934709573Sraf } 41034709573Sraf 41134709573Sraf void 41234709573Sraf _cancel_epilogue(void) 41334709573Sraf { 41434709573Sraf ulwp_t *self = curthread; 41534709573Sraf 41634709573Sraf if (self->ul_cancel_prologue == 0) { 41734709573Sraf self->ul_sp = 0; 41834709573Sraf self->ul_cancel_async = self->ul_save_async; 41934709573Sraf } 42034709573Sraf } 42134709573Sraf 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate int 4267c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 4277c478bd9Sstevel@tonic-gate { 4287c478bd9Sstevel@tonic-gate int error; 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate PROLOGUE 4317c478bd9Sstevel@tonic-gate while ((error = __lwp_wait(tid, found)) == EINTR) 4327c478bd9Sstevel@tonic-gate ; 4337c478bd9Sstevel@tonic-gate EPILOGUE 4347c478bd9Sstevel@tonic-gate return (error); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate ssize_t 4387c478bd9Sstevel@tonic-gate read(int fd, void *buf, size_t size) 4397c478bd9Sstevel@tonic-gate { 4407c478bd9Sstevel@tonic-gate extern ssize_t _read(int, void *, size_t); 4417c478bd9Sstevel@tonic-gate ssize_t rv; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate PERFORM(_read(fd, buf, size)) 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate ssize_t 4477c478bd9Sstevel@tonic-gate write(int fd, const void *buf, size_t size) 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate extern ssize_t _write(int, const void *, size_t); 4507c478bd9Sstevel@tonic-gate ssize_t rv; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate PERFORM(_write(fd, buf, size)) 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate int 4567c478bd9Sstevel@tonic-gate getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4577c478bd9Sstevel@tonic-gate int *flagsp) 4587c478bd9Sstevel@tonic-gate { 4597c478bd9Sstevel@tonic-gate extern int _getmsg(int, struct strbuf *, struct strbuf *, int *); 4607c478bd9Sstevel@tonic-gate int rv; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate PERFORM(_getmsg(fd, ctlptr, dataptr, flagsp)) 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate int 4667c478bd9Sstevel@tonic-gate getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4677c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 4687c478bd9Sstevel@tonic-gate { 4697c478bd9Sstevel@tonic-gate extern int _getpmsg(int, struct strbuf *, struct strbuf *, 4707c478bd9Sstevel@tonic-gate int *, int *); 4717c478bd9Sstevel@tonic-gate int rv; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate PERFORM(_getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate int 4777c478bd9Sstevel@tonic-gate putmsg(int fd, const struct strbuf *ctlptr, 4787c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4797c478bd9Sstevel@tonic-gate { 4807c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 4817c478bd9Sstevel@tonic-gate const struct strbuf *, int); 4827c478bd9Sstevel@tonic-gate int rv; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags)) 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate int 4887c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 4897c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 4927c478bd9Sstevel@tonic-gate const struct strbuf *, int); 4937c478bd9Sstevel@tonic-gate int rv; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate int 4997c478bd9Sstevel@tonic-gate putpmsg(int fd, const struct strbuf *ctlptr, 5007c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5017c478bd9Sstevel@tonic-gate { 5027c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 5037c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 5047c478bd9Sstevel@tonic-gate int rv; 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags)) 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate int 5107c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 5117c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 5147c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 5157c478bd9Sstevel@tonic-gate int rv; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 520f841f6adSraf #pragma weak nanosleep = _nanosleep 5217c478bd9Sstevel@tonic-gate int 522f841f6adSraf _nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 5237c478bd9Sstevel@tonic-gate { 5247c478bd9Sstevel@tonic-gate int error; 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate PROLOGUE 527f841f6adSraf error = __nanosleep(rqtp, rmtp); 5287c478bd9Sstevel@tonic-gate EPILOGUE 5297c478bd9Sstevel@tonic-gate if (error) { 5307c478bd9Sstevel@tonic-gate errno = error; 5317c478bd9Sstevel@tonic-gate return (-1); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate return (0); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 536f841f6adSraf #pragma weak clock_nanosleep = _clock_nanosleep 5377c478bd9Sstevel@tonic-gate int 538f841f6adSraf _clock_nanosleep(clockid_t clock_id, int flags, 5397c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate timespec_t reltime; 5427c478bd9Sstevel@tonic-gate hrtime_t start; 5437c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 5447c478bd9Sstevel@tonic-gate hrtime_t lapse; 5457c478bd9Sstevel@tonic-gate int error; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate switch (clock_id) { 5487c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 5497c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 5507c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 5517c478bd9Sstevel@tonic-gate return (ENOTSUP); 5527c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 5537c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 5547c478bd9Sstevel@tonic-gate break; 5557c478bd9Sstevel@tonic-gate default: 5567c478bd9Sstevel@tonic-gate return (EINVAL); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5597c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5607c478bd9Sstevel@tonic-gate rmtp = NULL; 5617c478bd9Sstevel@tonic-gate } else { 5627c478bd9Sstevel@tonic-gate reltime = *rqtp; 5637c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 5647c478bd9Sstevel@tonic-gate start = gethrtime(); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate restart: 5677c478bd9Sstevel@tonic-gate PROLOGUE 568f841f6adSraf error = __nanosleep(&reltime, rmtp); 5697c478bd9Sstevel@tonic-gate EPILOGUE 5707c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 5717c478bd9Sstevel@tonic-gate /* 5727c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 5737c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 5747c478bd9Sstevel@tonic-gate * the system clock. 5757c478bd9Sstevel@tonic-gate */ 5767c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5777c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 5787c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 5797c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5807c478bd9Sstevel@tonic-gate goto restart; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate } else { 5837c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 5847c478bd9Sstevel@tonic-gate rqtp->tv_nsec; 5857c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 5867c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 5877c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 5887c478bd9Sstevel@tonic-gate goto restart; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 5937c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 5947c478bd9Sstevel@tonic-gate /* 5957c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 5967c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 5977c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 5987c478bd9Sstevel@tonic-gate * 5997c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 6007c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 6017c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 6027c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 6037c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 6047c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 6057c478bd9Sstevel@tonic-gate */ 6067c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6077c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 6087c478bd9Sstevel@tonic-gate goto restart; 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate return (error); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate #pragma weak sleep = _sleep 6147c478bd9Sstevel@tonic-gate unsigned int 6157c478bd9Sstevel@tonic-gate _sleep(unsigned int sec) 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate unsigned int rem = 0; 6187c478bd9Sstevel@tonic-gate int error; 6197c478bd9Sstevel@tonic-gate timespec_t ts; 6207c478bd9Sstevel@tonic-gate timespec_t tsr; 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 6237c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 6247c478bd9Sstevel@tonic-gate PROLOGUE 625f841f6adSraf error = __nanosleep(&ts, &tsr); 6267c478bd9Sstevel@tonic-gate EPILOGUE 6277c478bd9Sstevel@tonic-gate if (error == EINTR) { 6287c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 6297c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 6307c478bd9Sstevel@tonic-gate rem++; 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate return (rem); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate #pragma weak usleep = _usleep 6367c478bd9Sstevel@tonic-gate int 6377c478bd9Sstevel@tonic-gate _usleep(useconds_t usec) 6387c478bd9Sstevel@tonic-gate { 6397c478bd9Sstevel@tonic-gate timespec_t ts; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 6427c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 6437c478bd9Sstevel@tonic-gate PROLOGUE 644f841f6adSraf (void) __nanosleep(&ts, NULL); 6457c478bd9Sstevel@tonic-gate EPILOGUE 6467c478bd9Sstevel@tonic-gate return (0); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate int 6507c478bd9Sstevel@tonic-gate close(int fildes) 6517c478bd9Sstevel@tonic-gate { 652f841f6adSraf extern void _aio_close(int); 6537c478bd9Sstevel@tonic-gate extern int _close(int); 6547c478bd9Sstevel@tonic-gate int rv; 6557c478bd9Sstevel@tonic-gate 656f841f6adSraf _aio_close(fildes); 6577c478bd9Sstevel@tonic-gate PERFORM(_close(fildes)) 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate int 6617c478bd9Sstevel@tonic-gate creat(const char *path, mode_t mode) 6627c478bd9Sstevel@tonic-gate { 6637c478bd9Sstevel@tonic-gate extern int _creat(const char *, mode_t); 6647c478bd9Sstevel@tonic-gate int rv; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate PERFORM(_creat(path, mode)) 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate #if !defined(_LP64) 6707c478bd9Sstevel@tonic-gate int 6717c478bd9Sstevel@tonic-gate creat64(const char *path, mode_t mode) 6727c478bd9Sstevel@tonic-gate { 6737c478bd9Sstevel@tonic-gate extern int _creat64(const char *, mode_t); 6747c478bd9Sstevel@tonic-gate int rv; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate PERFORM(_creat64(path, mode)) 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate int 6817c478bd9Sstevel@tonic-gate fcntl(int fildes, int cmd, ...) 6827c478bd9Sstevel@tonic-gate { 6837c478bd9Sstevel@tonic-gate extern int _fcntl(int, int, ...); 6847c478bd9Sstevel@tonic-gate intptr_t arg; 6857c478bd9Sstevel@tonic-gate int rv; 6867c478bd9Sstevel@tonic-gate va_list ap; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate va_start(ap, cmd); 6897c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 6907c478bd9Sstevel@tonic-gate va_end(ap); 6917c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 6927c478bd9Sstevel@tonic-gate return (_fcntl(fildes, cmd, arg)); 6937c478bd9Sstevel@tonic-gate PERFORM(_fcntl(fildes, cmd, arg)) 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate 696*1f8cf95fSraf int 697*1f8cf95fSraf fdatasync(int fildes) 698*1f8cf95fSraf { 699*1f8cf95fSraf extern int _fdatasync(int); 700*1f8cf95fSraf int rv; 701*1f8cf95fSraf 702*1f8cf95fSraf PERFORM(_fdatasync(fildes)) 703*1f8cf95fSraf } 704*1f8cf95fSraf 7057c478bd9Sstevel@tonic-gate int 7067c478bd9Sstevel@tonic-gate fsync(int fildes) 7077c478bd9Sstevel@tonic-gate { 7087c478bd9Sstevel@tonic-gate extern int _fsync(int); 7097c478bd9Sstevel@tonic-gate int rv; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate PERFORM(_fsync(fildes)) 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate int 7157c478bd9Sstevel@tonic-gate lockf(int fildes, int function, off_t size) 7167c478bd9Sstevel@tonic-gate { 7177c478bd9Sstevel@tonic-gate extern int _lockf(int, int, off_t); 7187c478bd9Sstevel@tonic-gate int rv; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate PERFORM(_lockf(fildes, function, size)) 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7247c478bd9Sstevel@tonic-gate int 7257c478bd9Sstevel@tonic-gate lockf64(int fildes, int function, off64_t size) 7267c478bd9Sstevel@tonic-gate { 7277c478bd9Sstevel@tonic-gate extern int _lockf64(int, int, off64_t); 7287c478bd9Sstevel@tonic-gate int rv; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate PERFORM(_lockf64(fildes, function, size)) 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate ssize_t 7357c478bd9Sstevel@tonic-gate msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 7367c478bd9Sstevel@tonic-gate { 7377c478bd9Sstevel@tonic-gate extern ssize_t _msgrcv(int, void *, size_t, long, int); 7387c478bd9Sstevel@tonic-gate ssize_t rv; 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate PERFORM(_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate int 7447c478bd9Sstevel@tonic-gate msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 7457c478bd9Sstevel@tonic-gate { 7467c478bd9Sstevel@tonic-gate extern int _msgsnd(int, const void *, size_t, int); 7477c478bd9Sstevel@tonic-gate int rv; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate PERFORM(_msgsnd(msqid, msgp, msgsz, msgflg)) 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate int 7537c478bd9Sstevel@tonic-gate msync(caddr_t addr, size_t len, int flags) 7547c478bd9Sstevel@tonic-gate { 7557c478bd9Sstevel@tonic-gate extern int _msync(caddr_t, size_t, int); 7567c478bd9Sstevel@tonic-gate int rv; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate PERFORM(_msync(addr, len, flags)) 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate int 7627c478bd9Sstevel@tonic-gate open(const char *path, int oflag, ...) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate extern int _open(const char *, int, ...); 7657c478bd9Sstevel@tonic-gate mode_t mode; 7667c478bd9Sstevel@tonic-gate int rv; 7677c478bd9Sstevel@tonic-gate va_list ap; 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7707c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7717c478bd9Sstevel@tonic-gate va_end(ap); 7727c478bd9Sstevel@tonic-gate PERFORM(_open(path, oflag, mode)) 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7767c478bd9Sstevel@tonic-gate int 7777c478bd9Sstevel@tonic-gate open64(const char *path, int oflag, ...) 7787c478bd9Sstevel@tonic-gate { 7797c478bd9Sstevel@tonic-gate extern int _open64(const char *, int, ...); 7807c478bd9Sstevel@tonic-gate mode_t mode; 7817c478bd9Sstevel@tonic-gate int rv; 7827c478bd9Sstevel@tonic-gate va_list ap; 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7857c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7867c478bd9Sstevel@tonic-gate va_end(ap); 7877c478bd9Sstevel@tonic-gate PERFORM(_open64(path, oflag, mode)) 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate int 7927c478bd9Sstevel@tonic-gate pause(void) 7937c478bd9Sstevel@tonic-gate { 7947c478bd9Sstevel@tonic-gate extern int _pause(void); 7957c478bd9Sstevel@tonic-gate int rv; 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate PERFORM(_pause()) 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate ssize_t 8017c478bd9Sstevel@tonic-gate pread(int fildes, void *buf, size_t nbyte, off_t offset) 8027c478bd9Sstevel@tonic-gate { 8037c478bd9Sstevel@tonic-gate extern ssize_t _pread(int, void *, size_t, off_t); 8047c478bd9Sstevel@tonic-gate ssize_t rv; 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate PERFORM(_pread(fildes, buf, nbyte, offset)) 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate #if !defined(_LP64) 8107c478bd9Sstevel@tonic-gate ssize_t 8117c478bd9Sstevel@tonic-gate pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 8127c478bd9Sstevel@tonic-gate { 8137c478bd9Sstevel@tonic-gate extern ssize_t _pread64(int, void *, size_t, off64_t); 8147c478bd9Sstevel@tonic-gate ssize_t rv; 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate PERFORM(_pread64(fildes, buf, nbyte, offset)) 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate ssize_t 8217c478bd9Sstevel@tonic-gate pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 8227c478bd9Sstevel@tonic-gate { 8237c478bd9Sstevel@tonic-gate extern ssize_t _pwrite(int, const void *, size_t, off_t); 8247c478bd9Sstevel@tonic-gate ssize_t rv; 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate PERFORM(_pwrite(fildes, buf, nbyte, offset)) 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate #if !defined(_LP64) 8307c478bd9Sstevel@tonic-gate ssize_t 8317c478bd9Sstevel@tonic-gate pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 8327c478bd9Sstevel@tonic-gate { 8337c478bd9Sstevel@tonic-gate extern ssize_t _pwrite64(int, const void *, size_t, off64_t); 8347c478bd9Sstevel@tonic-gate ssize_t rv; 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate PERFORM(_pwrite64(fildes, buf, nbyte, offset)) 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate ssize_t 8417c478bd9Sstevel@tonic-gate readv(int fildes, const struct iovec *iov, int iovcnt) 8427c478bd9Sstevel@tonic-gate { 8437c478bd9Sstevel@tonic-gate extern ssize_t _readv(int, const struct iovec *, int); 8447c478bd9Sstevel@tonic-gate ssize_t rv; 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate PERFORM(_readv(fildes, iov, iovcnt)) 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate int 8507c478bd9Sstevel@tonic-gate sigpause(int sig) 8517c478bd9Sstevel@tonic-gate { 8527c478bd9Sstevel@tonic-gate extern int _sigpause(int); 8537c478bd9Sstevel@tonic-gate int rv; 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate PERFORM(_sigpause(sig)) 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate #pragma weak sigsuspend = _sigsuspend 8597c478bd9Sstevel@tonic-gate int 8607c478bd9Sstevel@tonic-gate _sigsuspend(const sigset_t *set) 8617c478bd9Sstevel@tonic-gate { 8627c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 8637c478bd9Sstevel@tonic-gate int rv; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 8667c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 8677c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8687c478bd9Sstevel@tonic-gate return (rv); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate int 8727c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 8737c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 8747c478bd9Sstevel@tonic-gate { 8757c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 8767c478bd9Sstevel@tonic-gate const sigset_t *); 8777c478bd9Sstevel@tonic-gate int rv; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 8807c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 8817c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8827c478bd9Sstevel@tonic-gate return (rv); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 885f841f6adSraf #pragma weak sigtimedwait = _sigtimedwait 8867c478bd9Sstevel@tonic-gate int 887f841f6adSraf _sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout) 8887c478bd9Sstevel@tonic-gate { 889f841f6adSraf extern int __sigtimedwait(const sigset_t *, siginfo_t *, 8907c478bd9Sstevel@tonic-gate const timespec_t *); 8917c478bd9Sstevel@tonic-gate siginfo_t info; 8927c478bd9Sstevel@tonic-gate int sig; 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate PROLOGUE 895f841f6adSraf sig = __sigtimedwait(set, &info, timeout); 8967c478bd9Sstevel@tonic-gate if (sig == SIGCANCEL && 8977c478bd9Sstevel@tonic-gate (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 8987c478bd9Sstevel@tonic-gate do_sigcancel(); 8997c478bd9Sstevel@tonic-gate errno = EINTR; 9007c478bd9Sstevel@tonic-gate sig = -1; 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate EPILOGUE 9037c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 9040293487cSraf (void) _private_memcpy(infop, &info, sizeof (*infop)); 9057c478bd9Sstevel@tonic-gate return (sig); 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate #pragma weak sigwait = _sigwait 9097c478bd9Sstevel@tonic-gate int 9107c478bd9Sstevel@tonic-gate _sigwait(sigset_t *set) 9117c478bd9Sstevel@tonic-gate { 912f841f6adSraf return (_sigtimedwait(set, NULL, NULL)); 913f841f6adSraf } 914f841f6adSraf 915f841f6adSraf #pragma weak sigwaitinfo = _sigwaitinfo 916f841f6adSraf int 917f841f6adSraf _sigwaitinfo(const sigset_t *set, siginfo_t *info) 918f841f6adSraf { 919f841f6adSraf return (_sigtimedwait(set, info, NULL)); 920f841f6adSraf } 921f841f6adSraf 922f841f6adSraf #pragma weak sigqueue = _sigqueue 923f841f6adSraf int 924f841f6adSraf _sigqueue(pid_t pid, int signo, const union sigval value) 925f841f6adSraf { 926f841f6adSraf extern int __sigqueue(pid_t pid, int signo, 927f841f6adSraf /* const union sigval */ void *value, int si_code, int block); 928f841f6adSraf return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0)); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate int 9327c478bd9Sstevel@tonic-gate tcdrain(int fildes) 9337c478bd9Sstevel@tonic-gate { 9347c478bd9Sstevel@tonic-gate extern int _tcdrain(int); 9357c478bd9Sstevel@tonic-gate int rv; 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate PERFORM(_tcdrain(fildes)) 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate pid_t 9417c478bd9Sstevel@tonic-gate wait(int *stat_loc) 9427c478bd9Sstevel@tonic-gate { 9437c478bd9Sstevel@tonic-gate extern pid_t _wait(int *); 9447c478bd9Sstevel@tonic-gate pid_t rv; 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate PERFORM(_wait(stat_loc)) 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate pid_t 9507c478bd9Sstevel@tonic-gate wait3(int *statusp, int options, struct rusage *rusage) 9517c478bd9Sstevel@tonic-gate { 9527c478bd9Sstevel@tonic-gate extern pid_t _wait3(int *, int, struct rusage *); 9537c478bd9Sstevel@tonic-gate pid_t rv; 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate PERFORM(_wait3(statusp, options, rusage)) 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate int 9597c478bd9Sstevel@tonic-gate waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 9607c478bd9Sstevel@tonic-gate { 9617c478bd9Sstevel@tonic-gate extern int _waitid(idtype_t, id_t, siginfo_t *, int); 9627c478bd9Sstevel@tonic-gate int rv; 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate PERFORM(_waitid(idtype, id, infop, options)) 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 967e8031f0aSraf /* 968e8031f0aSraf * waitpid_cancel() is a libc-private symbol for internal use 969e8031f0aSraf * where cancellation semantics is desired (see system()). 970e8031f0aSraf */ 971e8031f0aSraf #pragma weak waitpid_cancel = waitpid 9727c478bd9Sstevel@tonic-gate pid_t 9737c478bd9Sstevel@tonic-gate waitpid(pid_t pid, int *stat_loc, int options) 9747c478bd9Sstevel@tonic-gate { 9757c478bd9Sstevel@tonic-gate extern pid_t _waitpid(pid_t, int *, int); 9767c478bd9Sstevel@tonic-gate pid_t rv; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate PERFORM(_waitpid(pid, stat_loc, options)) 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate ssize_t 9827c478bd9Sstevel@tonic-gate writev(int fildes, const struct iovec *iov, int iovcnt) 9837c478bd9Sstevel@tonic-gate { 9847c478bd9Sstevel@tonic-gate extern ssize_t _writev(int, const struct iovec *, int); 9857c478bd9Sstevel@tonic-gate ssize_t rv; 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate PERFORM(_writev(fildes, iov, iovcnt)) 9887c478bd9Sstevel@tonic-gate } 989