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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22*0293487cSraf 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include "lint.h" 317c478bd9Sstevel@tonic-gate #include "thr_uberdata.h" 327c478bd9Sstevel@tonic-gate #include <stdarg.h> 337c478bd9Sstevel@tonic-gate #include <poll.h> 347c478bd9Sstevel@tonic-gate #include <stropts.h> 357c478bd9Sstevel@tonic-gate #include <dlfcn.h> 367c478bd9Sstevel@tonic-gate #include <sys/uio.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate /* 397c478bd9Sstevel@tonic-gate * fork_lock is special -- We can't use lmutex_lock() (and thereby enter 407c478bd9Sstevel@tonic-gate * a critical region) because the second thread to reach this point would 417c478bd9Sstevel@tonic-gate * become unstoppable and the first thread would hang waiting for the 427c478bd9Sstevel@tonic-gate * second thread to stop itself. Therefore we don't use lmutex_lock() in 437c478bd9Sstevel@tonic-gate * fork_lock_enter(), but we do defer signals (the other form of concurrency). 447c478bd9Sstevel@tonic-gate * 457c478bd9Sstevel@tonic-gate * fork_lock_enter() does triple-duty. Not only does it serialize 467c478bd9Sstevel@tonic-gate * calls to fork() and forkall(), but it also serializes calls to 477c478bd9Sstevel@tonic-gate * thr_suspend() (fork() and forkall() also suspend other threads), 487c478bd9Sstevel@tonic-gate * and furthermore it serializes I18N calls to functions in other 497c478bd9Sstevel@tonic-gate * dlopen()ed L10N objects that might be calling malloc()/free(). 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static void 537c478bd9Sstevel@tonic-gate fork_lock_error(const char *who) 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate char msg[200]; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate (void) strlcpy(msg, "deadlock condition: ", sizeof (msg)); 587c478bd9Sstevel@tonic-gate (void) strlcat(msg, who, sizeof (msg)); 597c478bd9Sstevel@tonic-gate (void) strlcat(msg, "() called from a fork handler", sizeof (msg)); 607c478bd9Sstevel@tonic-gate thread_error(msg); 617c478bd9Sstevel@tonic-gate } 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate int 647c478bd9Sstevel@tonic-gate fork_lock_enter(const char *who) 657c478bd9Sstevel@tonic-gate { 667c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 677c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 687c478bd9Sstevel@tonic-gate int error = 0; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 717c478bd9Sstevel@tonic-gate sigoff(self); 727c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 737c478bd9Sstevel@tonic-gate while (udp->fork_count) { 747c478bd9Sstevel@tonic-gate if (udp->fork_owner == self) { 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate * This is like a recursive lock except that we 777c478bd9Sstevel@tonic-gate * inform the caller if we have been called from 787c478bd9Sstevel@tonic-gate * a fork handler and let it deal with that fact. 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate if (self->ul_fork) { 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * We have been called from a fork handler. 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate if (who != NULL && 857c478bd9Sstevel@tonic-gate udp->uberflags.uf_thread_error_detection) 867c478bd9Sstevel@tonic-gate fork_lock_error(who); 877c478bd9Sstevel@tonic-gate error = EDEADLK; 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate break; 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate ASSERT(self->ul_fork == 0); 927c478bd9Sstevel@tonic-gate (void) _cond_wait(&udp->fork_cond, &udp->fork_lock); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate udp->fork_owner = self; 957c478bd9Sstevel@tonic-gate udp->fork_count++; 967c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 977c478bd9Sstevel@tonic-gate return (error); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate void 1017c478bd9Sstevel@tonic-gate fork_lock_exit(void) 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1047c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate ASSERT(self->ul_critical == 0); 1077c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 1087c478bd9Sstevel@tonic-gate ASSERT(udp->fork_count != 0 && udp->fork_owner == self); 1097c478bd9Sstevel@tonic-gate if (--udp->fork_count == 0) { 1107c478bd9Sstevel@tonic-gate udp->fork_owner = NULL; 1117c478bd9Sstevel@tonic-gate (void) _cond_signal(&udp->fork_cond); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 1147c478bd9Sstevel@tonic-gate sigon(self); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * fork() is fork1() for both Posix threads and Solaris threads. 1197c478bd9Sstevel@tonic-gate * The forkall() interface exists for applications that require 1207c478bd9Sstevel@tonic-gate * the semantics of replicating all threads. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate #pragma weak fork = _fork1 1237c478bd9Sstevel@tonic-gate #pragma weak _fork = _fork1 1247c478bd9Sstevel@tonic-gate #pragma weak fork1 = _fork1 1257c478bd9Sstevel@tonic-gate pid_t 1267c478bd9Sstevel@tonic-gate _fork1(void) 1277c478bd9Sstevel@tonic-gate { 1287c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1297c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1307c478bd9Sstevel@tonic-gate pid_t pid; 1317c478bd9Sstevel@tonic-gate int error; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 1347c478bd9Sstevel@tonic-gate /* 1357c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 1367c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 1377c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 1387c478bd9Sstevel@tonic-gate * must never call fork(). 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 1417c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1427c478bd9Sstevel@tonic-gate return (-1); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate pid = __fork1(); 1457c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1467c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 1477c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate return (pid); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("fork")) != 0) { 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate fork_lock_exit(); 1577c478bd9Sstevel@tonic-gate errno = error; 1587c478bd9Sstevel@tonic-gate return (-1); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate self->ul_fork = 1; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 1647c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 1657c478bd9Sstevel@tonic-gate * internal libc locks while invoking them. The fork_lock_enter() 1667c478bd9Sstevel@tonic-gate * function serializes fork(), thr_suspend(), pthread_atfork() and 1677c478bd9Sstevel@tonic-gate * dlclose() (which destroys whatever pthread_atfork() functions 1687c478bd9Sstevel@tonic-gate * the library may have set up). If one of these pthread_atfork() 1697c478bd9Sstevel@tonic-gate * functions attempts to fork or suspend another thread or call 1707c478bd9Sstevel@tonic-gate * pthread_atfork() or dlclose a library, it will detect a deadlock 1717c478bd9Sstevel@tonic-gate * in fork_lock_enter(). Otherwise, the pthread_atfork() functions 1727c478bd9Sstevel@tonic-gate * are free to do anything they please (except they will not 1737c478bd9Sstevel@tonic-gate * receive any signals). 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate _prefork_handler(); 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * Block all signals. 1797c478bd9Sstevel@tonic-gate * Just deferring them via sigon() is not enough. 1807c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 1817c478bd9Sstevel@tonic-gate * that was actually sent to the parent before __fork1(). 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate block_all_signals(self); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 1877c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 1887c478bd9Sstevel@tonic-gate * Thus, we are assured that no library locks are held 1897c478bd9Sstevel@tonic-gate * while we invoke fork1() from the current thread. 1907c478bd9Sstevel@tonic-gate */ 1917c478bd9Sstevel@tonic-gate (void) _private_mutex_lock(&udp->fork_lock); 1927c478bd9Sstevel@tonic-gate suspend_fork(); 1937c478bd9Sstevel@tonic-gate (void) _private_mutex_unlock(&udp->fork_lock); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate pid = __fork1(); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 2007c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 2017c478bd9Sstevel@tonic-gate * Because we blocked all signals before __fork1(), a 2027c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2057c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2067c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2077c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2087c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2097c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 2107c478bd9Sstevel@tonic-gate _postfork1_child(); 2117c478bd9Sstevel@tonic-gate restore_signals(self); 2127c478bd9Sstevel@tonic-gate _postfork_child_handler(); 2137c478bd9Sstevel@tonic-gate } else { 2147c478bd9Sstevel@tonic-gate /* restart all threads that were suspended for fork1() */ 2157c478bd9Sstevel@tonic-gate continue_fork(0); 2167c478bd9Sstevel@tonic-gate restore_signals(self); 2177c478bd9Sstevel@tonic-gate _postfork_parent_handler(); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2217c478bd9Sstevel@tonic-gate fork_lock_exit(); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate return (pid); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * Much of the logic here is the same as in fork1(). 2287c478bd9Sstevel@tonic-gate * See the comments in fork1(), above. 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate #pragma weak forkall = _forkall 2317c478bd9Sstevel@tonic-gate pid_t 2327c478bd9Sstevel@tonic-gate _forkall(void) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 2357c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 2367c478bd9Sstevel@tonic-gate pid_t pid; 2377c478bd9Sstevel@tonic-gate int error; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 2407c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 2417c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2427c478bd9Sstevel@tonic-gate return (-1); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate pid = __forkall(); 2457c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2467c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2477c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate return (pid); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if ((error = fork_lock_enter("forkall")) != 0) { 2537c478bd9Sstevel@tonic-gate fork_lock_exit(); 2547c478bd9Sstevel@tonic-gate errno = error; 2557c478bd9Sstevel@tonic-gate return (-1); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate self->ul_fork = 1; 2587c478bd9Sstevel@tonic-gate block_all_signals(self); 2597c478bd9Sstevel@tonic-gate suspend_fork(); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate pid = __forkall(); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (pid == 0) { 2647c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2657c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2667c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2677c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2687c478bd9Sstevel@tonic-gate udp->pid = _private_getpid(); 2697c478bd9Sstevel@tonic-gate continue_fork(1); 2707c478bd9Sstevel@tonic-gate } else { 2717c478bd9Sstevel@tonic-gate continue_fork(0); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate restore_signals(self); 2747c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2757c478bd9Sstevel@tonic-gate fork_lock_exit(); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate return (pid); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Hacks for system calls to provide cancellation 2827c478bd9Sstevel@tonic-gate * and improve java garbage collection. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate #define PROLOGUE \ 2857c478bd9Sstevel@tonic-gate { \ 2867c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 2877c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 2887c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 2897c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 2907c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 2917c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 2927c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 2937c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED); \ 2947c478bd9Sstevel@tonic-gate } \ 2957c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate #define EPILOGUE \ 2997c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3007c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3017c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3027c478bd9Sstevel@tonic-gate } \ 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 3077c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 3087c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 3097c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 3107c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 3137c478bd9Sstevel@tonic-gate PROLOGUE \ 3147c478bd9Sstevel@tonic-gate if (nocancel) \ 3157c478bd9Sstevel@tonic-gate return (function_call); \ 3167c478bd9Sstevel@tonic-gate rv = function_call; \ 3177c478bd9Sstevel@tonic-gate EPILOGUE \ 3187c478bd9Sstevel@tonic-gate return (rv); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 3227c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 3237c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 3247c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 3257c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 3267c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 3277c478bd9Sstevel@tonic-gate * for the particular signal. 3287c478bd9Sstevel@tonic-gate * 3297c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 3307c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 3317c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 3347c478bd9Sstevel@tonic-gate { \ 3357c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 3367c478bd9Sstevel@tonic-gate int nocancel = (self->ul_vfork | self->ul_nocancel); \ 3377c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 3387c478bd9Sstevel@tonic-gate if (sigmask) { \ 3397c478bd9Sstevel@tonic-gate block_all_signals(self); \ 340*0293487cSraf self->ul_tmpmask.__sigbits[0] = sigmask->__sigbits[0]; \ 341*0293487cSraf self->ul_tmpmask.__sigbits[1] = sigmask->__sigbits[1]; \ 3427c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 3437c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 3447c478bd9Sstevel@tonic-gate } \ 3457c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3467c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3477c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3487c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3497c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 3507c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3517c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 3527c478bd9Sstevel@tonic-gate restore_signals(self); \ 3537c478bd9Sstevel@tonic-gate } \ 3547c478bd9Sstevel@tonic-gate _pthread_exit(PTHREAD_CANCELED);\ 3557c478bd9Sstevel@tonic-gate } \ 3567c478bd9Sstevel@tonic-gate } \ 3577c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 3587c478bd9Sstevel@tonic-gate } \ 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 3637c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 3647c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 3657c478bd9Sstevel@tonic-gate * original signal mask ourself. 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 3687c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3697c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3707c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3717c478bd9Sstevel@tonic-gate } \ 3727c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 3737c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 3747c478bd9Sstevel@tonic-gate restore_signals(self); \ 3757c478bd9Sstevel@tonic-gate } \ 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 3807c478bd9Sstevel@tonic-gate */ 3817c478bd9Sstevel@tonic-gate int 3827c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 3837c478bd9Sstevel@tonic-gate { 3847c478bd9Sstevel@tonic-gate int error; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate PROLOGUE 3877c478bd9Sstevel@tonic-gate while ((error = __lwp_wait(tid, found)) == EINTR) 3887c478bd9Sstevel@tonic-gate ; 3897c478bd9Sstevel@tonic-gate EPILOGUE 3907c478bd9Sstevel@tonic-gate return (error); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate ssize_t 3947c478bd9Sstevel@tonic-gate read(int fd, void *buf, size_t size) 3957c478bd9Sstevel@tonic-gate { 3967c478bd9Sstevel@tonic-gate extern ssize_t _read(int, void *, size_t); 3977c478bd9Sstevel@tonic-gate ssize_t rv; 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate PERFORM(_read(fd, buf, size)) 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate ssize_t 4037c478bd9Sstevel@tonic-gate write(int fd, const void *buf, size_t size) 4047c478bd9Sstevel@tonic-gate { 4057c478bd9Sstevel@tonic-gate extern ssize_t _write(int, const void *, size_t); 4067c478bd9Sstevel@tonic-gate ssize_t rv; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate PERFORM(_write(fd, buf, size)) 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate int 4127c478bd9Sstevel@tonic-gate getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4137c478bd9Sstevel@tonic-gate int *flagsp) 4147c478bd9Sstevel@tonic-gate { 4157c478bd9Sstevel@tonic-gate extern int _getmsg(int, struct strbuf *, struct strbuf *, int *); 4167c478bd9Sstevel@tonic-gate int rv; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate PERFORM(_getmsg(fd, ctlptr, dataptr, flagsp)) 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate int 4227c478bd9Sstevel@tonic-gate getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 4237c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 4247c478bd9Sstevel@tonic-gate { 4257c478bd9Sstevel@tonic-gate extern int _getpmsg(int, struct strbuf *, struct strbuf *, 4267c478bd9Sstevel@tonic-gate int *, int *); 4277c478bd9Sstevel@tonic-gate int rv; 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate PERFORM(_getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate int 4337c478bd9Sstevel@tonic-gate putmsg(int fd, const struct strbuf *ctlptr, 4347c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4357c478bd9Sstevel@tonic-gate { 4367c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 4377c478bd9Sstevel@tonic-gate const struct strbuf *, int); 4387c478bd9Sstevel@tonic-gate int rv; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags)) 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate int 4447c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 4457c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 4467c478bd9Sstevel@tonic-gate { 4477c478bd9Sstevel@tonic-gate extern int _putmsg(int, const struct strbuf *, 4487c478bd9Sstevel@tonic-gate const struct strbuf *, int); 4497c478bd9Sstevel@tonic-gate int rv; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate PERFORM(_putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate int 4557c478bd9Sstevel@tonic-gate putpmsg(int fd, const struct strbuf *ctlptr, 4567c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 4577c478bd9Sstevel@tonic-gate { 4587c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 4597c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 4607c478bd9Sstevel@tonic-gate int rv; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags)) 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate int 4667c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 4677c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 4687c478bd9Sstevel@tonic-gate { 4697c478bd9Sstevel@tonic-gate extern int _putpmsg(int, const struct strbuf *, 4707c478bd9Sstevel@tonic-gate const struct strbuf *, int, int); 4717c478bd9Sstevel@tonic-gate int rv; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate PERFORM(_putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate int 4777c478bd9Sstevel@tonic-gate __nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 4787c478bd9Sstevel@tonic-gate { 4797c478bd9Sstevel@tonic-gate int error; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate PROLOGUE 4827c478bd9Sstevel@tonic-gate error = ___nanosleep(rqtp, rmtp); 4837c478bd9Sstevel@tonic-gate EPILOGUE 4847c478bd9Sstevel@tonic-gate if (error) { 4857c478bd9Sstevel@tonic-gate errno = error; 4867c478bd9Sstevel@tonic-gate return (-1); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate return (0); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate int 4927c478bd9Sstevel@tonic-gate __clock_nanosleep(clockid_t clock_id, int flags, 4937c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate timespec_t reltime; 4967c478bd9Sstevel@tonic-gate hrtime_t start; 4977c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 4987c478bd9Sstevel@tonic-gate hrtime_t lapse; 4997c478bd9Sstevel@tonic-gate int error; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate switch (clock_id) { 5027c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 5037c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 5047c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 5057c478bd9Sstevel@tonic-gate return (ENOTSUP); 5067c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 5077c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 5087c478bd9Sstevel@tonic-gate break; 5097c478bd9Sstevel@tonic-gate default: 5107c478bd9Sstevel@tonic-gate return (EINVAL); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5137c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5147c478bd9Sstevel@tonic-gate rmtp = NULL; 5157c478bd9Sstevel@tonic-gate } else { 5167c478bd9Sstevel@tonic-gate reltime = *rqtp; 5177c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 5187c478bd9Sstevel@tonic-gate start = gethrtime(); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate restart: 5217c478bd9Sstevel@tonic-gate PROLOGUE 5227c478bd9Sstevel@tonic-gate error = ___nanosleep(&reltime, rmtp); 5237c478bd9Sstevel@tonic-gate EPILOGUE 5247c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 5257c478bd9Sstevel@tonic-gate /* 5267c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 5277c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 5287c478bd9Sstevel@tonic-gate * the system clock. 5297c478bd9Sstevel@tonic-gate */ 5307c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 5317c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 5327c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 5337c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5347c478bd9Sstevel@tonic-gate goto restart; 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate } else { 5377c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 5387c478bd9Sstevel@tonic-gate rqtp->tv_nsec; 5397c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 5407c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 5417c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 5427c478bd9Sstevel@tonic-gate goto restart; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 5477c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 5487c478bd9Sstevel@tonic-gate /* 5497c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 5507c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 5517c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 5527c478bd9Sstevel@tonic-gate * 5537c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 5547c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 5557c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 5567c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 5577c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 5587c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 5597c478bd9Sstevel@tonic-gate */ 5607c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 5617c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 5627c478bd9Sstevel@tonic-gate goto restart; 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate return (error); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate #pragma weak sleep = _sleep 5687c478bd9Sstevel@tonic-gate unsigned int 5697c478bd9Sstevel@tonic-gate _sleep(unsigned int sec) 5707c478bd9Sstevel@tonic-gate { 5717c478bd9Sstevel@tonic-gate unsigned int rem = 0; 5727c478bd9Sstevel@tonic-gate int error; 5737c478bd9Sstevel@tonic-gate timespec_t ts; 5747c478bd9Sstevel@tonic-gate timespec_t tsr; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 5777c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 5787c478bd9Sstevel@tonic-gate PROLOGUE 5797c478bd9Sstevel@tonic-gate error = ___nanosleep(&ts, &tsr); 5807c478bd9Sstevel@tonic-gate EPILOGUE 5817c478bd9Sstevel@tonic-gate if (error == EINTR) { 5827c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 5837c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 5847c478bd9Sstevel@tonic-gate rem++; 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate return (rem); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate #pragma weak usleep = _usleep 5907c478bd9Sstevel@tonic-gate int 5917c478bd9Sstevel@tonic-gate _usleep(useconds_t usec) 5927c478bd9Sstevel@tonic-gate { 5937c478bd9Sstevel@tonic-gate timespec_t ts; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 5967c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 5977c478bd9Sstevel@tonic-gate PROLOGUE 5987c478bd9Sstevel@tonic-gate (void) ___nanosleep(&ts, NULL); 5997c478bd9Sstevel@tonic-gate EPILOGUE 6007c478bd9Sstevel@tonic-gate return (0); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate int 6047c478bd9Sstevel@tonic-gate close(int fildes) 6057c478bd9Sstevel@tonic-gate { 6067c478bd9Sstevel@tonic-gate extern int _close(int); 6077c478bd9Sstevel@tonic-gate int rv; 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate PERFORM(_close(fildes)) 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate int 6137c478bd9Sstevel@tonic-gate creat(const char *path, mode_t mode) 6147c478bd9Sstevel@tonic-gate { 6157c478bd9Sstevel@tonic-gate extern int _creat(const char *, mode_t); 6167c478bd9Sstevel@tonic-gate int rv; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate PERFORM(_creat(path, mode)) 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate #if !defined(_LP64) 6227c478bd9Sstevel@tonic-gate int 6237c478bd9Sstevel@tonic-gate creat64(const char *path, mode_t mode) 6247c478bd9Sstevel@tonic-gate { 6257c478bd9Sstevel@tonic-gate extern int _creat64(const char *, mode_t); 6267c478bd9Sstevel@tonic-gate int rv; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate PERFORM(_creat64(path, mode)) 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate int 6337c478bd9Sstevel@tonic-gate fcntl(int fildes, int cmd, ...) 6347c478bd9Sstevel@tonic-gate { 6357c478bd9Sstevel@tonic-gate extern int _fcntl(int, int, ...); 6367c478bd9Sstevel@tonic-gate intptr_t arg; 6377c478bd9Sstevel@tonic-gate int rv; 6387c478bd9Sstevel@tonic-gate va_list ap; 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate va_start(ap, cmd); 6417c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 6427c478bd9Sstevel@tonic-gate va_end(ap); 6437c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 6447c478bd9Sstevel@tonic-gate return (_fcntl(fildes, cmd, arg)); 6457c478bd9Sstevel@tonic-gate PERFORM(_fcntl(fildes, cmd, arg)) 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate int 6497c478bd9Sstevel@tonic-gate fsync(int fildes) 6507c478bd9Sstevel@tonic-gate { 6517c478bd9Sstevel@tonic-gate extern int _fsync(int); 6527c478bd9Sstevel@tonic-gate int rv; 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate PERFORM(_fsync(fildes)) 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate int 6587c478bd9Sstevel@tonic-gate lockf(int fildes, int function, off_t size) 6597c478bd9Sstevel@tonic-gate { 6607c478bd9Sstevel@tonic-gate extern int _lockf(int, int, off_t); 6617c478bd9Sstevel@tonic-gate int rv; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate PERFORM(_lockf(fildes, function, size)) 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate #if !defined(_LP64) 6677c478bd9Sstevel@tonic-gate int 6687c478bd9Sstevel@tonic-gate lockf64(int fildes, int function, off64_t size) 6697c478bd9Sstevel@tonic-gate { 6707c478bd9Sstevel@tonic-gate extern int _lockf64(int, int, off64_t); 6717c478bd9Sstevel@tonic-gate int rv; 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate PERFORM(_lockf64(fildes, function, size)) 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate ssize_t 6787c478bd9Sstevel@tonic-gate msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 6797c478bd9Sstevel@tonic-gate { 6807c478bd9Sstevel@tonic-gate extern ssize_t _msgrcv(int, void *, size_t, long, int); 6817c478bd9Sstevel@tonic-gate ssize_t rv; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate PERFORM(_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate int 6877c478bd9Sstevel@tonic-gate msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 6887c478bd9Sstevel@tonic-gate { 6897c478bd9Sstevel@tonic-gate extern int _msgsnd(int, const void *, size_t, int); 6907c478bd9Sstevel@tonic-gate int rv; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate PERFORM(_msgsnd(msqid, msgp, msgsz, msgflg)) 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate int 6967c478bd9Sstevel@tonic-gate msync(caddr_t addr, size_t len, int flags) 6977c478bd9Sstevel@tonic-gate { 6987c478bd9Sstevel@tonic-gate extern int _msync(caddr_t, size_t, int); 6997c478bd9Sstevel@tonic-gate int rv; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate PERFORM(_msync(addr, len, flags)) 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate int 7057c478bd9Sstevel@tonic-gate open(const char *path, int oflag, ...) 7067c478bd9Sstevel@tonic-gate { 7077c478bd9Sstevel@tonic-gate extern int _open(const char *, int, ...); 7087c478bd9Sstevel@tonic-gate mode_t mode; 7097c478bd9Sstevel@tonic-gate int rv; 7107c478bd9Sstevel@tonic-gate va_list ap; 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7137c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7147c478bd9Sstevel@tonic-gate va_end(ap); 7157c478bd9Sstevel@tonic-gate PERFORM(_open(path, oflag, mode)) 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7197c478bd9Sstevel@tonic-gate int 7207c478bd9Sstevel@tonic-gate open64(const char *path, int oflag, ...) 7217c478bd9Sstevel@tonic-gate { 7227c478bd9Sstevel@tonic-gate extern int _open64(const char *, int, ...); 7237c478bd9Sstevel@tonic-gate mode_t mode; 7247c478bd9Sstevel@tonic-gate int rv; 7257c478bd9Sstevel@tonic-gate va_list ap; 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate va_start(ap, oflag); 7287c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 7297c478bd9Sstevel@tonic-gate va_end(ap); 7307c478bd9Sstevel@tonic-gate PERFORM(_open64(path, oflag, mode)) 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate int 7357c478bd9Sstevel@tonic-gate pause(void) 7367c478bd9Sstevel@tonic-gate { 7377c478bd9Sstevel@tonic-gate extern int _pause(void); 7387c478bd9Sstevel@tonic-gate int rv; 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate PERFORM(_pause()) 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate ssize_t 7447c478bd9Sstevel@tonic-gate pread(int fildes, void *buf, size_t nbyte, off_t offset) 7457c478bd9Sstevel@tonic-gate { 7467c478bd9Sstevel@tonic-gate extern ssize_t _pread(int, void *, size_t, off_t); 7477c478bd9Sstevel@tonic-gate ssize_t rv; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate PERFORM(_pread(fildes, buf, nbyte, offset)) 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7537c478bd9Sstevel@tonic-gate ssize_t 7547c478bd9Sstevel@tonic-gate pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 7557c478bd9Sstevel@tonic-gate { 7567c478bd9Sstevel@tonic-gate extern ssize_t _pread64(int, void *, size_t, off64_t); 7577c478bd9Sstevel@tonic-gate ssize_t rv; 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate PERFORM(_pread64(fildes, buf, nbyte, offset)) 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate ssize_t 7647c478bd9Sstevel@tonic-gate pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 7657c478bd9Sstevel@tonic-gate { 7667c478bd9Sstevel@tonic-gate extern ssize_t _pwrite(int, const void *, size_t, off_t); 7677c478bd9Sstevel@tonic-gate ssize_t rv; 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate PERFORM(_pwrite(fildes, buf, nbyte, offset)) 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7737c478bd9Sstevel@tonic-gate ssize_t 7747c478bd9Sstevel@tonic-gate pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 7757c478bd9Sstevel@tonic-gate { 7767c478bd9Sstevel@tonic-gate extern ssize_t _pwrite64(int, const void *, size_t, off64_t); 7777c478bd9Sstevel@tonic-gate ssize_t rv; 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate PERFORM(_pwrite64(fildes, buf, nbyte, offset)) 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate ssize_t 7847c478bd9Sstevel@tonic-gate readv(int fildes, const struct iovec *iov, int iovcnt) 7857c478bd9Sstevel@tonic-gate { 7867c478bd9Sstevel@tonic-gate extern ssize_t _readv(int, const struct iovec *, int); 7877c478bd9Sstevel@tonic-gate ssize_t rv; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate PERFORM(_readv(fildes, iov, iovcnt)) 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate int 7937c478bd9Sstevel@tonic-gate sigpause(int sig) 7947c478bd9Sstevel@tonic-gate { 7957c478bd9Sstevel@tonic-gate extern int _sigpause(int); 7967c478bd9Sstevel@tonic-gate int rv; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate PERFORM(_sigpause(sig)) 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate #pragma weak sigsuspend = _sigsuspend 8027c478bd9Sstevel@tonic-gate int 8037c478bd9Sstevel@tonic-gate _sigsuspend(const sigset_t *set) 8047c478bd9Sstevel@tonic-gate { 8057c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 8067c478bd9Sstevel@tonic-gate int rv; 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 8097c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 8107c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8117c478bd9Sstevel@tonic-gate return (rv); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate int 8157c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 8167c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 8177c478bd9Sstevel@tonic-gate { 8187c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 8197c478bd9Sstevel@tonic-gate const sigset_t *); 8207c478bd9Sstevel@tonic-gate int rv; 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 8237c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 8247c478bd9Sstevel@tonic-gate EPILOGUE_MASK 8257c478bd9Sstevel@tonic-gate return (rv); 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate int 8297c478bd9Sstevel@tonic-gate __sigtimedwait(const sigset_t *set, siginfo_t *infop, 8307c478bd9Sstevel@tonic-gate const timespec_t *timeout) 8317c478bd9Sstevel@tonic-gate { 8327c478bd9Sstevel@tonic-gate extern int ___sigtimedwait(const sigset_t *, siginfo_t *, 8337c478bd9Sstevel@tonic-gate const timespec_t *); 8347c478bd9Sstevel@tonic-gate siginfo_t info; 8357c478bd9Sstevel@tonic-gate int sig; 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate PROLOGUE 8387c478bd9Sstevel@tonic-gate sig = ___sigtimedwait(set, &info, timeout); 8397c478bd9Sstevel@tonic-gate if (sig == SIGCANCEL && 8407c478bd9Sstevel@tonic-gate (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 8417c478bd9Sstevel@tonic-gate do_sigcancel(); 8427c478bd9Sstevel@tonic-gate errno = EINTR; 8437c478bd9Sstevel@tonic-gate sig = -1; 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate EPILOGUE 8467c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 847*0293487cSraf (void) _private_memcpy(infop, &info, sizeof (*infop)); 8487c478bd9Sstevel@tonic-gate return (sig); 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate #pragma weak sigwait = _sigwait 8527c478bd9Sstevel@tonic-gate int 8537c478bd9Sstevel@tonic-gate _sigwait(sigset_t *set) 8547c478bd9Sstevel@tonic-gate { 8557c478bd9Sstevel@tonic-gate return (__sigtimedwait(set, NULL, NULL)); 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate int 8597c478bd9Sstevel@tonic-gate tcdrain(int fildes) 8607c478bd9Sstevel@tonic-gate { 8617c478bd9Sstevel@tonic-gate extern int _tcdrain(int); 8627c478bd9Sstevel@tonic-gate int rv; 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate PERFORM(_tcdrain(fildes)) 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate pid_t 8687c478bd9Sstevel@tonic-gate wait(int *stat_loc) 8697c478bd9Sstevel@tonic-gate { 8707c478bd9Sstevel@tonic-gate extern pid_t _wait(int *); 8717c478bd9Sstevel@tonic-gate pid_t rv; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate PERFORM(_wait(stat_loc)) 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate pid_t 8777c478bd9Sstevel@tonic-gate wait3(int *statusp, int options, struct rusage *rusage) 8787c478bd9Sstevel@tonic-gate { 8797c478bd9Sstevel@tonic-gate extern pid_t _wait3(int *, int, struct rusage *); 8807c478bd9Sstevel@tonic-gate pid_t rv; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate PERFORM(_wait3(statusp, options, rusage)) 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate int 8867c478bd9Sstevel@tonic-gate waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 8877c478bd9Sstevel@tonic-gate { 8887c478bd9Sstevel@tonic-gate extern int _waitid(idtype_t, id_t, siginfo_t *, int); 8897c478bd9Sstevel@tonic-gate int rv; 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate PERFORM(_waitid(idtype, id, infop, options)) 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate pid_t 8957c478bd9Sstevel@tonic-gate waitpid(pid_t pid, int *stat_loc, int options) 8967c478bd9Sstevel@tonic-gate { 8977c478bd9Sstevel@tonic-gate extern pid_t _waitpid(pid_t, int *, int); 8987c478bd9Sstevel@tonic-gate pid_t rv; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate PERFORM(_waitpid(pid, stat_loc, options)) 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate ssize_t 9047c478bd9Sstevel@tonic-gate writev(int fildes, const struct iovec *iov, int iovcnt) 9057c478bd9Sstevel@tonic-gate { 9067c478bd9Sstevel@tonic-gate extern ssize_t _writev(int, const struct iovec *, int); 9077c478bd9Sstevel@tonic-gate ssize_t rv; 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate PERFORM(_writev(fildes, iov, iovcnt)) 9107c478bd9Sstevel@tonic-gate } 911