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 /* 238fd04b83SRoger A. Faulkner * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*5dbfd19aSTheo Schlossnagle /* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */ 28*5dbfd19aSTheo Schlossnagle 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> 35a574db85Sraf #include <wait.h> 36a574db85Sraf #include <sys/socket.h> 377c478bd9Sstevel@tonic-gate #include <sys/uio.h> 38a574db85Sraf #include <sys/file.h> 39a574db85Sraf #include <sys/door.h> 407c478bd9Sstevel@tonic-gate 417257d1b4Sraf /* 427257d1b4Sraf * These leading-underbar symbols exist because mistakes were made 437257d1b4Sraf * in the past that put them into non-SUNWprivate versions of 447257d1b4Sraf * the libc mapfiles. They should be eliminated, but oh well... 457257d1b4Sraf */ 467257d1b4Sraf #pragma weak _fork = fork 477257d1b4Sraf #pragma weak _read = read 487257d1b4Sraf #pragma weak _write = write 497257d1b4Sraf #pragma weak _getmsg = getmsg 507257d1b4Sraf #pragma weak _getpmsg = getpmsg 517257d1b4Sraf #pragma weak _putmsg = putmsg 527257d1b4Sraf #pragma weak _putpmsg = putpmsg 537257d1b4Sraf #pragma weak _sleep = sleep 547257d1b4Sraf #pragma weak _close = close 557257d1b4Sraf #pragma weak _creat = creat 567257d1b4Sraf #pragma weak _fcntl = fcntl 577257d1b4Sraf #pragma weak _fsync = fsync 587257d1b4Sraf #pragma weak _lockf = lockf 597257d1b4Sraf #pragma weak _msgrcv = msgrcv 607257d1b4Sraf #pragma weak _msgsnd = msgsnd 617257d1b4Sraf #pragma weak _msync = msync 627257d1b4Sraf #pragma weak _open = open 637257d1b4Sraf #pragma weak _openat = openat 647257d1b4Sraf #pragma weak _pause = pause 657257d1b4Sraf #pragma weak _readv = readv 667257d1b4Sraf #pragma weak _sigpause = sigpause 677257d1b4Sraf #pragma weak _sigsuspend = sigsuspend 687257d1b4Sraf #pragma weak _tcdrain = tcdrain 697257d1b4Sraf #pragma weak _waitid = waitid 707257d1b4Sraf #pragma weak _writev = writev 717257d1b4Sraf 727257d1b4Sraf #if !defined(_LP64) 737257d1b4Sraf #pragma weak _creat64 = creat64 747257d1b4Sraf #pragma weak _lockf64 = lockf64 757257d1b4Sraf #pragma weak _open64 = open64 767257d1b4Sraf #pragma weak _openat64 = openat64 777257d1b4Sraf #pragma weak _pread64 = pread64 787257d1b4Sraf #pragma weak _pwrite64 = pwrite64 797257d1b4Sraf #endif 807257d1b4Sraf 81d56c62ccSraf /* 82d56c62ccSraf * These are SUNWprivate, but they are being used by Sun Studio libcollector. 83d56c62ccSraf */ 84d56c62ccSraf #pragma weak _fork1 = fork1 85d56c62ccSraf #pragma weak _forkall = forkall 86d56c62ccSraf 877c478bd9Sstevel@tonic-gate /* 8898c1a6b4Sraf * atfork_lock protects the pthread_atfork() data structures. 8998c1a6b4Sraf * 90b6233ca5Sraf * fork_lock does double-duty. Not only does it (and atfork_lock) 91b6233ca5Sraf * serialize calls to fork() and forkall(), but it also serializes calls 92b6233ca5Sraf * to thr_suspend() and thr_continue() (because fork() and forkall() also 93b6233ca5Sraf * suspend and continue other threads and they want no competition). 94b6233ca5Sraf * 9598c1a6b4Sraf * Functions called in dlopen()ed L10N objects can do anything, including 9698c1a6b4Sraf * call malloc() and free(). Such calls are not fork-safe when protected 9798c1a6b4Sraf * by an ordinary mutex that is acquired in libc's prefork processing 9898c1a6b4Sraf * because, with an interposed malloc library present, there would be a 9998c1a6b4Sraf * lock ordering violation due to the pthread_atfork() prefork function 10098c1a6b4Sraf * in the interposition library acquiring its malloc lock(s) before the 101b6233ca5Sraf * ordinary mutex in libc being acquired by libc's prefork functions. 102b6233ca5Sraf * 10398c1a6b4Sraf * Within libc, calls to malloc() and free() are fork-safe if the calls 10498c1a6b4Sraf * are made while holding no other libc locks. This covers almost all 10598c1a6b4Sraf * of libc's malloc() and free() calls. For those libc code paths, such 10698c1a6b4Sraf * as the above-mentioned L10N calls, that require serialization and that 10798c1a6b4Sraf * may call malloc() or free(), libc uses callout_lock_enter() to perform 10898c1a6b4Sraf * the serialization. This works because callout_lock is not acquired as 10998c1a6b4Sraf * part of running the pthread_atfork() prefork handlers (to avoid the 11098c1a6b4Sraf * lock ordering violation described above). Rather, it is simply 11198c1a6b4Sraf * reinitialized in postfork1_child() to cover the case that some 11298c1a6b4Sraf * now-defunct thread might have been suspended while holding it. 1137c478bd9Sstevel@tonic-gate */ 114b6233ca5Sraf 1152e145884Sraf void 1162e145884Sraf fork_lock_enter(void) 1177c478bd9Sstevel@tonic-gate { 118b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 1198cd45542Sraf (void) mutex_lock(&curthread->ul_uberdata->fork_lock); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate void 1237c478bd9Sstevel@tonic-gate fork_lock_exit(void) 1247c478bd9Sstevel@tonic-gate { 125b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 1268cd45542Sraf (void) mutex_unlock(&curthread->ul_uberdata->fork_lock); 127b6233ca5Sraf } 128b6233ca5Sraf 129a574db85Sraf /* 130a574db85Sraf * Use cancel_safe_mutex_lock() to protect against being cancelled while 131a574db85Sraf * holding callout_lock and calling outside of libc (via L10N plugins). 132a574db85Sraf * We will honor a pending cancellation request when callout_lock_exit() 133a574db85Sraf * is called, by calling cancel_safe_mutex_unlock(). 134a574db85Sraf */ 135b6233ca5Sraf void 13698c1a6b4Sraf callout_lock_enter(void) 137b6233ca5Sraf { 138b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 139a574db85Sraf cancel_safe_mutex_lock(&curthread->ul_uberdata->callout_lock); 140b6233ca5Sraf } 1417c478bd9Sstevel@tonic-gate 142b6233ca5Sraf void 14398c1a6b4Sraf callout_lock_exit(void) 144b6233ca5Sraf { 145b6233ca5Sraf ASSERT(curthread->ul_critical == 0); 146a574db85Sraf cancel_safe_mutex_unlock(&curthread->ul_uberdata->callout_lock); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 149dfb96a4fSab pid_t 1507257d1b4Sraf forkx(int flags) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 1537c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 1547c478bd9Sstevel@tonic-gate pid_t pid; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * We are a child of vfork(); omit all of the fork 1597c478bd9Sstevel@tonic-gate * logic and go straight to the system call trap. 1607c478bd9Sstevel@tonic-gate * A vfork() child of a multithreaded parent 1617c478bd9Sstevel@tonic-gate * must never call fork(). 1627c478bd9Sstevel@tonic-gate */ 1637c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 1647c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1657c478bd9Sstevel@tonic-gate return (-1); 1667c478bd9Sstevel@tonic-gate } 167657b1f3dSraf pid = __forkx(flags); 1687c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 1698cd45542Sraf udp->pid = getpid(); 1707c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate return (pid); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1752e145884Sraf sigoff(self); 1762e145884Sraf if (self->ul_fork) { 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * Cannot call fork() from a fork handler. 1797c478bd9Sstevel@tonic-gate */ 1802e145884Sraf sigon(self); 1812e145884Sraf errno = EDEADLK; 1827c478bd9Sstevel@tonic-gate return (-1); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate self->ul_fork = 1; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * The functions registered by pthread_atfork() are defined by 1887c478bd9Sstevel@tonic-gate * the application and its libraries and we must not hold any 1892e145884Sraf * internal lmutex_lock()-acquired locks while invoking them. 1902e145884Sraf * We hold only udp->atfork_lock to protect the atfork linkages. 1912e145884Sraf * If one of these pthread_atfork() functions attempts to fork 192b6233ca5Sraf * or to call pthread_atfork(), libc will detect the error and 193b6233ca5Sraf * fail the call with EDEADLK. Otherwise, the pthread_atfork() 194b6233ca5Sraf * functions are free to do anything they please (except they 195b6233ca5Sraf * will not receive any signals). 1967c478bd9Sstevel@tonic-gate */ 1978cd45542Sraf (void) mutex_lock(&udp->atfork_lock); 1983771f298SRoger A. Faulkner 1993771f298SRoger A. Faulkner /* 2003771f298SRoger A. Faulkner * Posix (SUSv3) requires fork() to be async-signal-safe. 2013771f298SRoger A. Faulkner * This cannot be made to happen with fork handlers in place 2023771f298SRoger A. Faulkner * (they grab locks). To be in nominal compliance, don't run 2033771f298SRoger A. Faulkner * any fork handlers if we are called within a signal context. 2043771f298SRoger A. Faulkner * This leaves the child process in a questionable state with 2053771f298SRoger A. Faulkner * respect to its locks, but at least the parent process does 2063771f298SRoger A. Faulkner * not become deadlocked due to the calling thread attempting 2073771f298SRoger A. Faulkner * to acquire a lock that it already owns. 2083771f298SRoger A. Faulkner */ 2093771f298SRoger A. Faulkner if (self->ul_siglink == NULL) 2103771f298SRoger A. Faulkner _prefork_handler(); 2117c478bd9Sstevel@tonic-gate 2122e145884Sraf /* 2132e145884Sraf * Block every other thread attempting thr_suspend() or thr_continue(). 2142e145884Sraf */ 2158cd45542Sraf (void) mutex_lock(&udp->fork_lock); 2162e145884Sraf 2177c478bd9Sstevel@tonic-gate /* 2187c478bd9Sstevel@tonic-gate * Block all signals. 2192e145884Sraf * Just deferring them via sigoff() is not enough. 2207c478bd9Sstevel@tonic-gate * We have to avoid taking a deferred signal in the child 221657b1f3dSraf * that was actually sent to the parent before __forkx(). 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate block_all_signals(self); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * This suspends all threads but this one, leaving them 2277c478bd9Sstevel@tonic-gate * suspended outside of any critical regions in the library. 228b6233ca5Sraf * Thus, we are assured that no lmutex_lock()-acquired library 229b6233ca5Sraf * locks are held while we invoke fork() from the current thread. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate suspend_fork(); 2327c478bd9Sstevel@tonic-gate 233657b1f3dSraf pid = __forkx(flags); 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * Clear our schedctl pointer. 2387c478bd9Sstevel@tonic-gate * Discard any deferred signal that was sent to the parent. 239657b1f3dSraf * Because we blocked all signals before __forkx(), a 2407c478bd9Sstevel@tonic-gate * deferred signal cannot have been taken by the child. 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 2437c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 2447c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 2457c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 2468cd45542Sraf udp->pid = getpid(); 2477c478bd9Sstevel@tonic-gate /* reset the library's data structures to reflect one thread */ 248c242ec1bSRoger A. Faulkner unregister_locks(); 249f841f6adSraf postfork1_child(); 2507c478bd9Sstevel@tonic-gate restore_signals(self); 2518cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 2523771f298SRoger A. Faulkner if (self->ul_siglink == NULL) 2533771f298SRoger A. Faulkner _postfork_child_handler(); 2547c478bd9Sstevel@tonic-gate } else { 255657b1f3dSraf /* restart all threads that were suspended for fork() */ 2567c478bd9Sstevel@tonic-gate continue_fork(0); 2577c478bd9Sstevel@tonic-gate restore_signals(self); 2588cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 2593771f298SRoger A. Faulkner if (self->ul_siglink == NULL) 2603771f298SRoger A. Faulkner _postfork_parent_handler(); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2638cd45542Sraf (void) mutex_unlock(&udp->atfork_lock); 2647c478bd9Sstevel@tonic-gate self->ul_fork = 0; 2652e145884Sraf sigon(self); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate return (pid); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 271657b1f3dSraf * fork() is fork1() for both Posix threads and Solaris threads. 272657b1f3dSraf * The forkall() interface exists for applications that require 273657b1f3dSraf * the semantics of replicating all threads. 2747c478bd9Sstevel@tonic-gate */ 2757257d1b4Sraf #pragma weak fork1 = fork 2767c478bd9Sstevel@tonic-gate pid_t 2777257d1b4Sraf fork(void) 278657b1f3dSraf { 2797257d1b4Sraf return (forkx(0)); 280657b1f3dSraf } 281657b1f3dSraf 282657b1f3dSraf /* 283657b1f3dSraf * Much of the logic here is the same as in forkx(). 284657b1f3dSraf * See the comments in forkx(), above. 285657b1f3dSraf */ 286dfb96a4fSab pid_t 2877257d1b4Sraf forkallx(int flags) 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; 2907c478bd9Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata; 2917c478bd9Sstevel@tonic-gate pid_t pid; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate if (self->ul_vfork) { 2947c478bd9Sstevel@tonic-gate if (udp->uberflags.uf_mt) { 2957c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2967c478bd9Sstevel@tonic-gate return (-1); 2977c478bd9Sstevel@tonic-gate } 298657b1f3dSraf pid = __forkallx(flags); 2997c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 3008cd45542Sraf udp->pid = getpid(); 3017c478bd9Sstevel@tonic-gate self->ul_vfork = 0; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate return (pid); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3062e145884Sraf sigoff(self); 3072e145884Sraf if (self->ul_fork) { 3082e145884Sraf sigon(self); 3092e145884Sraf errno = EDEADLK; 3107c478bd9Sstevel@tonic-gate return (-1); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate self->ul_fork = 1; 3138cd45542Sraf (void) mutex_lock(&udp->atfork_lock); 3148cd45542Sraf (void) mutex_lock(&udp->fork_lock); 3157c478bd9Sstevel@tonic-gate block_all_signals(self); 3167c478bd9Sstevel@tonic-gate suspend_fork(); 3177c478bd9Sstevel@tonic-gate 318657b1f3dSraf pid = __forkallx(flags); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate if (pid == 0) { 3217c478bd9Sstevel@tonic-gate self->ul_schedctl_called = NULL; 3227c478bd9Sstevel@tonic-gate self->ul_schedctl = NULL; 3237c478bd9Sstevel@tonic-gate self->ul_cursig = 0; 3247c478bd9Sstevel@tonic-gate self->ul_siginfo.si_signo = 0; 3258cd45542Sraf udp->pid = getpid(); 326c242ec1bSRoger A. Faulkner unregister_locks(); 3277c478bd9Sstevel@tonic-gate continue_fork(1); 3287c478bd9Sstevel@tonic-gate } else { 3297c478bd9Sstevel@tonic-gate continue_fork(0); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate restore_signals(self); 3328cd45542Sraf (void) mutex_unlock(&udp->fork_lock); 3338cd45542Sraf (void) mutex_unlock(&udp->atfork_lock); 3342e145884Sraf self->ul_fork = 0; 3352e145884Sraf sigon(self); 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate return (pid); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 340657b1f3dSraf pid_t 3417257d1b4Sraf forkall(void) 342657b1f3dSraf { 3437257d1b4Sraf return (forkallx(0)); 344657b1f3dSraf } 345657b1f3dSraf 3467c478bd9Sstevel@tonic-gate /* 347a574db85Sraf * For the implementation of cancellation at cancellation points. 3487c478bd9Sstevel@tonic-gate */ 3497c478bd9Sstevel@tonic-gate #define PROLOGUE \ 3507c478bd9Sstevel@tonic-gate { \ 3517c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 352a574db85Sraf int nocancel = \ 353a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \ 354a574db85Sraf self->ul_critical | self->ul_sigdefer); \ 355a574db85Sraf int abort = 0; \ 3567c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3577c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 3587c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 3597c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 3607c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) \ 3617257d1b4Sraf pthread_exit(PTHREAD_CANCELED); \ 3627c478bd9Sstevel@tonic-gate } \ 3637c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 364a574db85Sraf } else if (self->ul_cancel_pending && \ 365a574db85Sraf !self->ul_cancel_disabled) { \ 366a574db85Sraf set_cancel_eintr_flag(self); \ 367a574db85Sraf abort = 1; \ 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate #define EPILOGUE \ 3717c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 3727c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 3737c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 3747c478bd9Sstevel@tonic-gate } \ 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * Perform the body of the action required by most of the cancelable 3797c478bd9Sstevel@tonic-gate * function calls. The return(function_call) part is to allow the 3807c478bd9Sstevel@tonic-gate * compiler to make the call be executed with tail recursion, which 3817c478bd9Sstevel@tonic-gate * saves a register window on sparc and slightly (not much) improves 3827c478bd9Sstevel@tonic-gate * the code for x86/x64 compilations. 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate #define PERFORM(function_call) \ 3857c478bd9Sstevel@tonic-gate PROLOGUE \ 386a574db85Sraf if (abort) { \ 387a574db85Sraf *self->ul_errnop = EINTR; \ 388a574db85Sraf return (-1); \ 389a574db85Sraf } \ 3907c478bd9Sstevel@tonic-gate if (nocancel) \ 3917c478bd9Sstevel@tonic-gate return (function_call); \ 3927c478bd9Sstevel@tonic-gate rv = function_call; \ 3937c478bd9Sstevel@tonic-gate EPILOGUE \ 3947c478bd9Sstevel@tonic-gate return (rv); 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * Specialized prologue for sigsuspend() and pollsys(). 3987c478bd9Sstevel@tonic-gate * These system calls pass a signal mask to the kernel. 3997c478bd9Sstevel@tonic-gate * The kernel replaces the thread's signal mask with the 4007c478bd9Sstevel@tonic-gate * temporary mask before the thread goes to sleep. If 4017c478bd9Sstevel@tonic-gate * a signal is received, the signal handler will execute 4027c478bd9Sstevel@tonic-gate * with the temporary mask, as modified by the sigaction 4037c478bd9Sstevel@tonic-gate * for the particular signal. 4047c478bd9Sstevel@tonic-gate * 4057c478bd9Sstevel@tonic-gate * We block all signals until we reach the kernel with the 4067c478bd9Sstevel@tonic-gate * temporary mask. This eliminates race conditions with 4077c478bd9Sstevel@tonic-gate * setting the signal mask while signals are being posted. 4087c478bd9Sstevel@tonic-gate */ 4097c478bd9Sstevel@tonic-gate #define PROLOGUE_MASK(sigmask) \ 4107c478bd9Sstevel@tonic-gate { \ 4117c478bd9Sstevel@tonic-gate ulwp_t *self = curthread; \ 412a574db85Sraf int nocancel = \ 413a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \ 414a574db85Sraf self->ul_critical | self->ul_sigdefer); \ 4157c478bd9Sstevel@tonic-gate if (!self->ul_vfork) { \ 4167c478bd9Sstevel@tonic-gate if (sigmask) { \ 4177c478bd9Sstevel@tonic-gate block_all_signals(self); \ 418bdf0047cSRoger A. Faulkner self->ul_tmpmask = *sigmask; \ 4197c478bd9Sstevel@tonic-gate delete_reserved_signals(&self->ul_tmpmask); \ 4207c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 1; \ 4217c478bd9Sstevel@tonic-gate } \ 4227c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4237c478bd9Sstevel@tonic-gate self->ul_save_async = self->ul_cancel_async; \ 4247c478bd9Sstevel@tonic-gate if (!self->ul_cancel_disabled) { \ 4257c478bd9Sstevel@tonic-gate self->ul_cancel_async = 1; \ 4267c478bd9Sstevel@tonic-gate if (self->ul_cancel_pending) { \ 4277c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4287c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0;\ 4297c478bd9Sstevel@tonic-gate restore_signals(self); \ 4307c478bd9Sstevel@tonic-gate } \ 4317257d1b4Sraf pthread_exit(PTHREAD_CANCELED); \ 4327c478bd9Sstevel@tonic-gate } \ 4337c478bd9Sstevel@tonic-gate } \ 4347c478bd9Sstevel@tonic-gate self->ul_sp = stkptr(); \ 4357c478bd9Sstevel@tonic-gate } \ 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * If a signal is taken, we return from the system call wrapper with 4407c478bd9Sstevel@tonic-gate * our original signal mask restored (see code in call_user_handler()). 4417c478bd9Sstevel@tonic-gate * If not (self->ul_sigsuspend is still non-zero), we must restore our 4427c478bd9Sstevel@tonic-gate * original signal mask ourself. 4437c478bd9Sstevel@tonic-gate */ 4447c478bd9Sstevel@tonic-gate #define EPILOGUE_MASK \ 4457c478bd9Sstevel@tonic-gate if (nocancel == 0) { \ 4467c478bd9Sstevel@tonic-gate self->ul_sp = 0; \ 4477c478bd9Sstevel@tonic-gate self->ul_cancel_async = self->ul_save_async; \ 4487c478bd9Sstevel@tonic-gate } \ 4497c478bd9Sstevel@tonic-gate if (self->ul_sigsuspend) { \ 4507c478bd9Sstevel@tonic-gate self->ul_sigsuspend = 0; \ 4517c478bd9Sstevel@tonic-gate restore_signals(self); \ 4527c478bd9Sstevel@tonic-gate } \ 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 45534709573Sraf /* 456f841f6adSraf * Cancellation prologue and epilogue functions, 457f841f6adSraf * for cancellation points too complex to include here. 45834709573Sraf */ 45934709573Sraf void 46034709573Sraf _cancel_prologue(void) 46134709573Sraf { 46234709573Sraf ulwp_t *self = curthread; 46334709573Sraf 464a574db85Sraf self->ul_cancel_prologue = 465a574db85Sraf (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | 466a574db85Sraf self->ul_critical | self->ul_sigdefer) != 0; 46734709573Sraf if (self->ul_cancel_prologue == 0) { 46834709573Sraf self->ul_save_async = self->ul_cancel_async; 46934709573Sraf if (!self->ul_cancel_disabled) { 47034709573Sraf self->ul_cancel_async = 1; 47134709573Sraf if (self->ul_cancel_pending) 4727257d1b4Sraf pthread_exit(PTHREAD_CANCELED); 47334709573Sraf } 47434709573Sraf self->ul_sp = stkptr(); 475a574db85Sraf } else if (self->ul_cancel_pending && 476a574db85Sraf !self->ul_cancel_disabled) { 477a574db85Sraf set_cancel_eintr_flag(self); 47834709573Sraf } 47934709573Sraf } 48034709573Sraf 48134709573Sraf void 48234709573Sraf _cancel_epilogue(void) 48334709573Sraf { 48434709573Sraf ulwp_t *self = curthread; 48534709573Sraf 48634709573Sraf if (self->ul_cancel_prologue == 0) { 48734709573Sraf self->ul_sp = 0; 48834709573Sraf self->ul_cancel_async = self->ul_save_async; 48934709573Sraf } 49034709573Sraf } 49134709573Sraf 4927c478bd9Sstevel@tonic-gate /* 4937c478bd9Sstevel@tonic-gate * Called from _thrp_join() (thr_join() is a cancellation point) 4947c478bd9Sstevel@tonic-gate */ 4957c478bd9Sstevel@tonic-gate int 4967c478bd9Sstevel@tonic-gate lwp_wait(thread_t tid, thread_t *found) 4977c478bd9Sstevel@tonic-gate { 4987c478bd9Sstevel@tonic-gate int error; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate PROLOGUE 501a574db85Sraf if (abort) 502a574db85Sraf return (EINTR); 503a574db85Sraf while ((error = __lwp_wait(tid, found)) == EINTR && !cancel_active()) 504a574db85Sraf continue; 5057c478bd9Sstevel@tonic-gate EPILOGUE 5067c478bd9Sstevel@tonic-gate return (error); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate ssize_t 5107257d1b4Sraf read(int fd, void *buf, size_t size) 5117c478bd9Sstevel@tonic-gate { 512a574db85Sraf extern ssize_t __read(int, void *, size_t); 5137c478bd9Sstevel@tonic-gate ssize_t rv; 5147c478bd9Sstevel@tonic-gate 515a574db85Sraf PERFORM(__read(fd, buf, size)) 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate ssize_t 5197257d1b4Sraf write(int fd, const void *buf, size_t size) 5207c478bd9Sstevel@tonic-gate { 521a574db85Sraf extern ssize_t __write(int, const void *, size_t); 5227c478bd9Sstevel@tonic-gate ssize_t rv; 5237c478bd9Sstevel@tonic-gate 524a574db85Sraf PERFORM(__write(fd, buf, size)) 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate int 5287257d1b4Sraf getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5297c478bd9Sstevel@tonic-gate int *flagsp) 5307c478bd9Sstevel@tonic-gate { 531a574db85Sraf extern int __getmsg(int, struct strbuf *, struct strbuf *, int *); 5327c478bd9Sstevel@tonic-gate int rv; 5337c478bd9Sstevel@tonic-gate 534a574db85Sraf PERFORM(__getmsg(fd, ctlptr, dataptr, flagsp)) 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate int 5387257d1b4Sraf getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, 5397c478bd9Sstevel@tonic-gate int *bandp, int *flagsp) 5407c478bd9Sstevel@tonic-gate { 541a574db85Sraf extern int __getpmsg(int, struct strbuf *, struct strbuf *, 5422e145884Sraf int *, int *); 5437c478bd9Sstevel@tonic-gate int rv; 5447c478bd9Sstevel@tonic-gate 545a574db85Sraf PERFORM(__getpmsg(fd, ctlptr, dataptr, bandp, flagsp)) 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate int 5497257d1b4Sraf putmsg(int fd, const struct strbuf *ctlptr, 5507c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5517c478bd9Sstevel@tonic-gate { 552a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5532e145884Sraf const struct strbuf *, int); 5547c478bd9Sstevel@tonic-gate int rv; 5557c478bd9Sstevel@tonic-gate 556a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags)) 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate int 5607c478bd9Sstevel@tonic-gate __xpg4_putmsg(int fd, const struct strbuf *ctlptr, 5617c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int flags) 5627c478bd9Sstevel@tonic-gate { 563a574db85Sraf extern int __putmsg(int, const struct strbuf *, 5642e145884Sraf const struct strbuf *, int); 5657c478bd9Sstevel@tonic-gate int rv; 5667c478bd9Sstevel@tonic-gate 567a574db85Sraf PERFORM(__putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4)) 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate int 5717257d1b4Sraf putpmsg(int fd, const struct strbuf *ctlptr, 5727c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5737c478bd9Sstevel@tonic-gate { 574a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5752e145884Sraf const struct strbuf *, int, int); 5767c478bd9Sstevel@tonic-gate int rv; 5777c478bd9Sstevel@tonic-gate 578a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags)) 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate int 5827c478bd9Sstevel@tonic-gate __xpg4_putpmsg(int fd, const struct strbuf *ctlptr, 5837c478bd9Sstevel@tonic-gate const struct strbuf *dataptr, int band, int flags) 5847c478bd9Sstevel@tonic-gate { 585a574db85Sraf extern int __putpmsg(int, const struct strbuf *, 5862e145884Sraf const struct strbuf *, int, int); 5877c478bd9Sstevel@tonic-gate int rv; 5887c478bd9Sstevel@tonic-gate 589a574db85Sraf PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4)) 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate int 5937257d1b4Sraf nanosleep(const timespec_t *rqtp, timespec_t *rmtp) 5947c478bd9Sstevel@tonic-gate { 5957c478bd9Sstevel@tonic-gate int error; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate PROLOGUE 598a574db85Sraf error = abort? EINTR : __nanosleep(rqtp, rmtp); 5997c478bd9Sstevel@tonic-gate EPILOGUE 6007c478bd9Sstevel@tonic-gate if (error) { 6017c478bd9Sstevel@tonic-gate errno = error; 6027c478bd9Sstevel@tonic-gate return (-1); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate return (0); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate int 6087257d1b4Sraf clock_nanosleep(clockid_t clock_id, int flags, 6097c478bd9Sstevel@tonic-gate const timespec_t *rqtp, timespec_t *rmtp) 6107c478bd9Sstevel@tonic-gate { 6117c478bd9Sstevel@tonic-gate timespec_t reltime; 6127c478bd9Sstevel@tonic-gate hrtime_t start; 6137c478bd9Sstevel@tonic-gate hrtime_t rqlapse; 6147c478bd9Sstevel@tonic-gate hrtime_t lapse; 6157c478bd9Sstevel@tonic-gate int error; 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate switch (clock_id) { 6187c478bd9Sstevel@tonic-gate case CLOCK_VIRTUAL: 6197c478bd9Sstevel@tonic-gate case CLOCK_PROCESS_CPUTIME_ID: 6207c478bd9Sstevel@tonic-gate case CLOCK_THREAD_CPUTIME_ID: 6217c478bd9Sstevel@tonic-gate return (ENOTSUP); 6227c478bd9Sstevel@tonic-gate case CLOCK_REALTIME: 6237c478bd9Sstevel@tonic-gate case CLOCK_HIGHRES: 6247c478bd9Sstevel@tonic-gate break; 6257c478bd9Sstevel@tonic-gate default: 6267c478bd9Sstevel@tonic-gate return (EINVAL); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6297c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6307c478bd9Sstevel@tonic-gate rmtp = NULL; 6317c478bd9Sstevel@tonic-gate } else { 6327c478bd9Sstevel@tonic-gate reltime = *rqtp; 6337c478bd9Sstevel@tonic-gate if (clock_id == CLOCK_HIGHRES) 6347c478bd9Sstevel@tonic-gate start = gethrtime(); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate restart: 6377c478bd9Sstevel@tonic-gate PROLOGUE 638a574db85Sraf error = abort? EINTR : __nanosleep(&reltime, rmtp); 6397c478bd9Sstevel@tonic-gate EPILOGUE 6407c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_HIGHRES) { 6417c478bd9Sstevel@tonic-gate /* 6427c478bd9Sstevel@tonic-gate * Don't return yet if we didn't really get a timeout. 6437c478bd9Sstevel@tonic-gate * This can happen if we return because someone resets 6447c478bd9Sstevel@tonic-gate * the system clock. 6457c478bd9Sstevel@tonic-gate */ 6467c478bd9Sstevel@tonic-gate if (flags & TIMER_ABSTIME) { 6477c478bd9Sstevel@tonic-gate if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6487c478bd9Sstevel@tonic-gate rqtp->tv_nsec > gethrtime()) { 6497c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6507c478bd9Sstevel@tonic-gate goto restart; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate } else { 6537c478bd9Sstevel@tonic-gate rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC + 6542e145884Sraf rqtp->tv_nsec; 6557c478bd9Sstevel@tonic-gate lapse = gethrtime() - start; 6567c478bd9Sstevel@tonic-gate if (rqlapse > lapse) { 6577c478bd9Sstevel@tonic-gate hrt2ts(rqlapse - lapse, &reltime); 6587c478bd9Sstevel@tonic-gate goto restart; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate if (error == 0 && clock_id == CLOCK_REALTIME && 6637c478bd9Sstevel@tonic-gate (flags & TIMER_ABSTIME)) { 6647c478bd9Sstevel@tonic-gate /* 6657c478bd9Sstevel@tonic-gate * Don't return yet just because someone reset the 6667c478bd9Sstevel@tonic-gate * system clock. Recompute the new relative time 6677c478bd9Sstevel@tonic-gate * and reissue the nanosleep() call if necessary. 6687c478bd9Sstevel@tonic-gate * 6697c478bd9Sstevel@tonic-gate * Resetting the system clock causes all sorts of 6707c478bd9Sstevel@tonic-gate * problems and the SUSV3 standards body should 6717c478bd9Sstevel@tonic-gate * have made the behavior of clock_nanosleep() be 6727c478bd9Sstevel@tonic-gate * implementation-defined in such a case rather than 6737c478bd9Sstevel@tonic-gate * being specific about honoring the new system time. 6747c478bd9Sstevel@tonic-gate * Standards bodies are filled with fools and idiots. 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate abstime_to_reltime(clock_id, rqtp, &reltime); 6777c478bd9Sstevel@tonic-gate if (reltime.tv_sec != 0 || reltime.tv_nsec != 0) 6787c478bd9Sstevel@tonic-gate goto restart; 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate return (error); 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate unsigned int 6847257d1b4Sraf sleep(unsigned int sec) 6857c478bd9Sstevel@tonic-gate { 6867c478bd9Sstevel@tonic-gate unsigned int rem = 0; 6877c478bd9Sstevel@tonic-gate timespec_t ts; 6887c478bd9Sstevel@tonic-gate timespec_t tsr; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)sec; 6917c478bd9Sstevel@tonic-gate ts.tv_nsec = 0; 6927257d1b4Sraf if (nanosleep(&ts, &tsr) == -1 && errno == EINTR) { 6937c478bd9Sstevel@tonic-gate rem = (unsigned int)tsr.tv_sec; 6947c478bd9Sstevel@tonic-gate if (tsr.tv_nsec >= NANOSEC / 2) 6957c478bd9Sstevel@tonic-gate rem++; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate return (rem); 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate int 7017257d1b4Sraf usleep(useconds_t usec) 7027c478bd9Sstevel@tonic-gate { 7037c478bd9Sstevel@tonic-gate timespec_t ts; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate ts.tv_sec = usec / MICROSEC; 7067c478bd9Sstevel@tonic-gate ts.tv_nsec = (long)(usec % MICROSEC) * 1000; 7077257d1b4Sraf (void) nanosleep(&ts, NULL); 7087c478bd9Sstevel@tonic-gate return (0); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate int 7127257d1b4Sraf close(int fildes) 7137c478bd9Sstevel@tonic-gate { 714f841f6adSraf extern void _aio_close(int); 715a574db85Sraf extern int __close(int); 7167c478bd9Sstevel@tonic-gate int rv; 7177c478bd9Sstevel@tonic-gate 718720d4a35Sraf /* 719720d4a35Sraf * If we call _aio_close() while in a critical region, 720720d4a35Sraf * we will draw an ASSERT() failure, so don't do it. 721720d4a35Sraf * No calls to close() from within libc need _aio_close(); 722720d4a35Sraf * only the application's calls to close() need this, 723720d4a35Sraf * and such calls are never from a libc critical region. 724720d4a35Sraf */ 725720d4a35Sraf if (curthread->ul_critical == 0) 726720d4a35Sraf _aio_close(fildes); 727a574db85Sraf PERFORM(__close(fildes)) 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate 730a574db85Sraf int 7317257d1b4Sraf door_call(int d, door_arg_t *params) 732a574db85Sraf { 733a574db85Sraf extern int __door_call(int, door_arg_t *); 734a574db85Sraf int rv; 735a574db85Sraf 736a574db85Sraf PERFORM(__door_call(d, params)) 737a574db85Sraf } 738a574db85Sraf 7397c478bd9Sstevel@tonic-gate int 7407257d1b4Sraf fcntl(int fildes, int cmd, ...) 7417c478bd9Sstevel@tonic-gate { 742a574db85Sraf extern int __fcntl(int, int, ...); 7437c478bd9Sstevel@tonic-gate intptr_t arg; 7447c478bd9Sstevel@tonic-gate int rv; 7457c478bd9Sstevel@tonic-gate va_list ap; 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate va_start(ap, cmd); 7487c478bd9Sstevel@tonic-gate arg = va_arg(ap, intptr_t); 7497c478bd9Sstevel@tonic-gate va_end(ap); 7507c478bd9Sstevel@tonic-gate if (cmd != F_SETLKW) 751a574db85Sraf return (__fcntl(fildes, cmd, arg)); 752a574db85Sraf PERFORM(__fcntl(fildes, cmd, arg)) 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7551f8cf95fSraf int 7567257d1b4Sraf fdatasync(int fildes) 7571f8cf95fSraf { 758a574db85Sraf extern int __fdsync(int, int); 7591f8cf95fSraf int rv; 7601f8cf95fSraf 761a574db85Sraf PERFORM(__fdsync(fildes, FDSYNC)) 7621f8cf95fSraf } 7631f8cf95fSraf 7647c478bd9Sstevel@tonic-gate int 7657257d1b4Sraf fsync(int fildes) 7667c478bd9Sstevel@tonic-gate { 767a574db85Sraf extern int __fdsync(int, int); 7687c478bd9Sstevel@tonic-gate int rv; 7697c478bd9Sstevel@tonic-gate 770a574db85Sraf PERFORM(__fdsync(fildes, FSYNC)) 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate int 7747257d1b4Sraf lockf(int fildes, int function, off_t size) 7757c478bd9Sstevel@tonic-gate { 776a574db85Sraf extern int __lockf(int, int, off_t); 7777c478bd9Sstevel@tonic-gate int rv; 7787c478bd9Sstevel@tonic-gate 779a574db85Sraf PERFORM(__lockf(fildes, function, size)) 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate #if !defined(_LP64) 7837c478bd9Sstevel@tonic-gate int 7847257d1b4Sraf lockf64(int fildes, int function, off64_t size) 7857c478bd9Sstevel@tonic-gate { 786a574db85Sraf extern int __lockf64(int, int, off64_t); 7877c478bd9Sstevel@tonic-gate int rv; 7887c478bd9Sstevel@tonic-gate 789a574db85Sraf PERFORM(__lockf64(fildes, function, size)) 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate ssize_t 7947257d1b4Sraf msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) 7957c478bd9Sstevel@tonic-gate { 796a574db85Sraf extern ssize_t __msgrcv(int, void *, size_t, long, int); 7977c478bd9Sstevel@tonic-gate ssize_t rv; 7987c478bd9Sstevel@tonic-gate 799a574db85Sraf PERFORM(__msgrcv(msqid, msgp, msgsz, msgtyp, msgflg)) 800a574db85Sraf } 801a574db85Sraf 802a574db85Sraf int 8037257d1b4Sraf msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) 804a574db85Sraf { 805a574db85Sraf extern int __msgsnd(int, const void *, size_t, int); 806a574db85Sraf int rv; 807a574db85Sraf 808a574db85Sraf PERFORM(__msgsnd(msqid, msgp, msgsz, msgflg)) 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate int 8127257d1b4Sraf msync(caddr_t addr, size_t len, int flags) 8137c478bd9Sstevel@tonic-gate { 814a574db85Sraf extern int __msync(caddr_t, size_t, int); 8157c478bd9Sstevel@tonic-gate int rv; 8167c478bd9Sstevel@tonic-gate 817a574db85Sraf PERFORM(__msync(addr, len, flags)) 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate int 8218fd04b83SRoger A. Faulkner openat(int fd, const char *path, int oflag, ...) 8227c478bd9Sstevel@tonic-gate { 823a574db85Sraf mode_t mode; 8247c478bd9Sstevel@tonic-gate int rv; 825a574db85Sraf va_list ap; 8267c478bd9Sstevel@tonic-gate 827a574db85Sraf va_start(ap, oflag); 828a574db85Sraf mode = va_arg(ap, mode_t); 829a574db85Sraf va_end(ap); 8308fd04b83SRoger A. Faulkner PERFORM(__openat(fd, path, oflag, mode)) 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate int 8348fd04b83SRoger A. Faulkner open(const char *path, int oflag, ...) 8357c478bd9Sstevel@tonic-gate { 8367c478bd9Sstevel@tonic-gate mode_t mode; 8377c478bd9Sstevel@tonic-gate int rv; 8387c478bd9Sstevel@tonic-gate va_list ap; 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8417c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8427c478bd9Sstevel@tonic-gate va_end(ap); 8438fd04b83SRoger A. Faulkner PERFORM(__open(path, oflag, mode)) 8448fd04b83SRoger A. Faulkner } 8458fd04b83SRoger A. Faulkner 8468fd04b83SRoger A. Faulkner int 8478fd04b83SRoger A. Faulkner creat(const char *path, mode_t mode) 8488fd04b83SRoger A. Faulkner { 8498fd04b83SRoger A. Faulkner return (open(path, O_WRONLY | O_CREAT | O_TRUNC, mode)); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate #if !defined(_LP64) 853a574db85Sraf int 8548fd04b83SRoger A. Faulkner openat64(int fd, const char *path, int oflag, ...) 855a574db85Sraf { 856a574db85Sraf mode_t mode; 857a574db85Sraf int rv; 858a574db85Sraf va_list ap; 859a574db85Sraf 860a574db85Sraf va_start(ap, oflag); 861a574db85Sraf mode = va_arg(ap, mode_t); 862a574db85Sraf va_end(ap); 8638fd04b83SRoger A. Faulkner PERFORM(__openat64(fd, path, oflag, mode)) 864a574db85Sraf } 865a574db85Sraf 8667c478bd9Sstevel@tonic-gate int 8678fd04b83SRoger A. Faulkner open64(const char *path, int oflag, ...) 8687c478bd9Sstevel@tonic-gate { 8697c478bd9Sstevel@tonic-gate mode_t mode; 8707c478bd9Sstevel@tonic-gate int rv; 8717c478bd9Sstevel@tonic-gate va_list ap; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate va_start(ap, oflag); 8747c478bd9Sstevel@tonic-gate mode = va_arg(ap, mode_t); 8757c478bd9Sstevel@tonic-gate va_end(ap); 8768fd04b83SRoger A. Faulkner PERFORM(__open64(path, oflag, mode)) 8778fd04b83SRoger A. Faulkner } 8788fd04b83SRoger A. Faulkner 8798fd04b83SRoger A. Faulkner int 8808fd04b83SRoger A. Faulkner creat64(const char *path, mode_t mode) 8818fd04b83SRoger A. Faulkner { 8828fd04b83SRoger A. Faulkner return (open64(path, O_WRONLY | O_CREAT | O_TRUNC, mode)); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate int 8877257d1b4Sraf pause(void) 8887c478bd9Sstevel@tonic-gate { 889a574db85Sraf extern int __pause(void); 8907c478bd9Sstevel@tonic-gate int rv; 8917c478bd9Sstevel@tonic-gate 892a574db85Sraf PERFORM(__pause()) 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate ssize_t 8967257d1b4Sraf pread(int fildes, void *buf, size_t nbyte, off_t offset) 8977c478bd9Sstevel@tonic-gate { 898a574db85Sraf extern ssize_t __pread(int, void *, size_t, off_t); 8997c478bd9Sstevel@tonic-gate ssize_t rv; 9007c478bd9Sstevel@tonic-gate 901a574db85Sraf PERFORM(__pread(fildes, buf, nbyte, offset)) 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate #if !defined(_LP64) 9057c478bd9Sstevel@tonic-gate ssize_t 9067257d1b4Sraf pread64(int fildes, void *buf, size_t nbyte, off64_t offset) 9077c478bd9Sstevel@tonic-gate { 908a574db85Sraf extern ssize_t __pread64(int, void *, size_t, off64_t); 9097c478bd9Sstevel@tonic-gate ssize_t rv; 9107c478bd9Sstevel@tonic-gate 911a574db85Sraf PERFORM(__pread64(fildes, buf, nbyte, offset)) 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate ssize_t 9167257d1b4Sraf pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) 9177c478bd9Sstevel@tonic-gate { 918a574db85Sraf extern ssize_t __pwrite(int, const void *, size_t, off_t); 9197c478bd9Sstevel@tonic-gate ssize_t rv; 9207c478bd9Sstevel@tonic-gate 921a574db85Sraf PERFORM(__pwrite(fildes, buf, nbyte, offset)) 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate #if !defined(_LP64) 9257c478bd9Sstevel@tonic-gate ssize_t 9267257d1b4Sraf pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset) 9277c478bd9Sstevel@tonic-gate { 928a574db85Sraf extern ssize_t __pwrite64(int, const void *, size_t, off64_t); 9297c478bd9Sstevel@tonic-gate ssize_t rv; 9307c478bd9Sstevel@tonic-gate 931a574db85Sraf PERFORM(__pwrite64(fildes, buf, nbyte, offset)) 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate ssize_t 9367257d1b4Sraf readv(int fildes, const struct iovec *iov, int iovcnt) 9377c478bd9Sstevel@tonic-gate { 938a574db85Sraf extern ssize_t __readv(int, const struct iovec *, int); 9397c478bd9Sstevel@tonic-gate ssize_t rv; 9407c478bd9Sstevel@tonic-gate 941a574db85Sraf PERFORM(__readv(fildes, iov, iovcnt)) 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate int 9457257d1b4Sraf sigpause(int sig) 9467c478bd9Sstevel@tonic-gate { 947a574db85Sraf extern int __sigpause(int); 9487c478bd9Sstevel@tonic-gate int rv; 9497c478bd9Sstevel@tonic-gate 950a574db85Sraf PERFORM(__sigpause(sig)) 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate int 9547257d1b4Sraf sigsuspend(const sigset_t *set) 9557c478bd9Sstevel@tonic-gate { 9567c478bd9Sstevel@tonic-gate extern int __sigsuspend(const sigset_t *); 9577c478bd9Sstevel@tonic-gate int rv; 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate PROLOGUE_MASK(set) 9607c478bd9Sstevel@tonic-gate rv = __sigsuspend(set); 9617c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9627c478bd9Sstevel@tonic-gate return (rv); 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate int 9667c478bd9Sstevel@tonic-gate _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout, 9677c478bd9Sstevel@tonic-gate const sigset_t *sigmask) 9687c478bd9Sstevel@tonic-gate { 9697c478bd9Sstevel@tonic-gate extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *, 9702e145884Sraf const sigset_t *); 9717c478bd9Sstevel@tonic-gate int rv; 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate PROLOGUE_MASK(sigmask) 9747c478bd9Sstevel@tonic-gate rv = __pollsys(fds, nfd, timeout, sigmask); 9757c478bd9Sstevel@tonic-gate EPILOGUE_MASK 9767c478bd9Sstevel@tonic-gate return (rv); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate int 9807257d1b4Sraf sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout) 9817c478bd9Sstevel@tonic-gate { 982f841f6adSraf extern int __sigtimedwait(const sigset_t *, siginfo_t *, 9832e145884Sraf const timespec_t *); 9847c478bd9Sstevel@tonic-gate siginfo_t info; 9857c478bd9Sstevel@tonic-gate int sig; 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate PROLOGUE 988a574db85Sraf if (abort) { 989a574db85Sraf *self->ul_errnop = EINTR; 9907c478bd9Sstevel@tonic-gate sig = -1; 991a574db85Sraf } else { 992a574db85Sraf sig = __sigtimedwait(set, &info, timeout); 993a574db85Sraf if (sig == SIGCANCEL && 994a574db85Sraf (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) { 995a574db85Sraf do_sigcancel(); 996a574db85Sraf *self->ul_errnop = EINTR; 997a574db85Sraf sig = -1; 998a574db85Sraf } 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate EPILOGUE 10017c478bd9Sstevel@tonic-gate if (sig != -1 && infop) 10028cd45542Sraf (void) memcpy(infop, &info, sizeof (*infop)); 10037c478bd9Sstevel@tonic-gate return (sig); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate int 10077257d1b4Sraf sigwait(sigset_t *set) 10087c478bd9Sstevel@tonic-gate { 10097257d1b4Sraf return (sigtimedwait(set, NULL, NULL)); 1010f841f6adSraf } 1011f841f6adSraf 1012f841f6adSraf int 10137257d1b4Sraf sigwaitinfo(const sigset_t *set, siginfo_t *info) 1014f841f6adSraf { 10157257d1b4Sraf return (sigtimedwait(set, info, NULL)); 1016f841f6adSraf } 1017f841f6adSraf 1018f841f6adSraf int 10197257d1b4Sraf sigqueue(pid_t pid, int signo, const union sigval value) 1020f841f6adSraf { 1021f841f6adSraf extern int __sigqueue(pid_t pid, int signo, 10222e145884Sraf /* const union sigval */ void *value, int si_code, int block); 1023f841f6adSraf return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0)); 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate int 1027*5dbfd19aSTheo Schlossnagle _so_accept(int sock, struct sockaddr *addr, uint_t *addrlen, int version, 1028*5dbfd19aSTheo Schlossnagle int flags) 10297c478bd9Sstevel@tonic-gate { 1030*5dbfd19aSTheo Schlossnagle extern int __so_accept(int, struct sockaddr *, uint_t *, int, int); 10317c478bd9Sstevel@tonic-gate int rv; 10327c478bd9Sstevel@tonic-gate 1033*5dbfd19aSTheo Schlossnagle PERFORM(__so_accept(sock, addr, addrlen, version, flags)) 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 1036a574db85Sraf int 1037a574db85Sraf _so_connect(int sock, struct sockaddr *addr, uint_t addrlen, int version) 10387c478bd9Sstevel@tonic-gate { 1039a574db85Sraf extern int __so_connect(int, struct sockaddr *, uint_t, int); 1040a574db85Sraf int rv; 10417c478bd9Sstevel@tonic-gate 1042a574db85Sraf PERFORM(__so_connect(sock, addr, addrlen, version)) 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate 1045a574db85Sraf int 1046a574db85Sraf _so_recv(int sock, void *buf, size_t len, int flags) 10477c478bd9Sstevel@tonic-gate { 1048a574db85Sraf extern int __so_recv(int, void *, size_t, int); 1049a574db85Sraf int rv; 10507c478bd9Sstevel@tonic-gate 1051a574db85Sraf PERFORM(__so_recv(sock, buf, len, flags)) 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate int 1055a574db85Sraf _so_recvfrom(int sock, void *buf, size_t len, int flags, 1056a574db85Sraf struct sockaddr *addr, int *addrlen) 10577c478bd9Sstevel@tonic-gate { 1058a574db85Sraf extern int __so_recvfrom(int, void *, size_t, int, 1059a574db85Sraf struct sockaddr *, int *); 10607c478bd9Sstevel@tonic-gate int rv; 10617c478bd9Sstevel@tonic-gate 1062a574db85Sraf PERFORM(__so_recvfrom(sock, buf, len, flags, addr, addrlen)) 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 1065a574db85Sraf int 1066a574db85Sraf _so_recvmsg(int sock, struct msghdr *msg, int flags) 1067a574db85Sraf { 1068a574db85Sraf extern int __so_recvmsg(int, struct msghdr *, int); 1069a574db85Sraf int rv; 1070a574db85Sraf 1071a574db85Sraf PERFORM(__so_recvmsg(sock, msg, flags)) 1072a574db85Sraf } 1073a574db85Sraf 1074a574db85Sraf int 1075a574db85Sraf _so_send(int sock, const void *buf, size_t len, int flags) 1076a574db85Sraf { 1077a574db85Sraf extern int __so_send(int, const void *, size_t, int); 1078a574db85Sraf int rv; 1079a574db85Sraf 1080a574db85Sraf PERFORM(__so_send(sock, buf, len, flags)) 1081a574db85Sraf } 1082a574db85Sraf 1083a574db85Sraf int 1084a574db85Sraf _so_sendmsg(int sock, const struct msghdr *msg, int flags) 10857c478bd9Sstevel@tonic-gate { 1086a574db85Sraf extern int __so_sendmsg(int, const struct msghdr *, int); 1087a574db85Sraf int rv; 1088a574db85Sraf 1089a574db85Sraf PERFORM(__so_sendmsg(sock, msg, flags)) 1090a574db85Sraf } 1091a574db85Sraf 1092a574db85Sraf int 1093a574db85Sraf _so_sendto(int sock, const void *buf, size_t len, int flags, 1094a574db85Sraf const struct sockaddr *addr, int *addrlen) 1095a574db85Sraf { 1096a574db85Sraf extern int __so_sendto(int, const void *, size_t, int, 1097a574db85Sraf const struct sockaddr *, int *); 1098a574db85Sraf int rv; 1099a574db85Sraf 1100a574db85Sraf PERFORM(__so_sendto(sock, buf, len, flags, addr, addrlen)) 1101a574db85Sraf } 1102a574db85Sraf 1103a574db85Sraf int 11047257d1b4Sraf tcdrain(int fildes) 1105a574db85Sraf { 1106a574db85Sraf extern int __tcdrain(int); 1107a574db85Sraf int rv; 1108a574db85Sraf 1109a574db85Sraf PERFORM(__tcdrain(fildes)) 1110a574db85Sraf } 1111a574db85Sraf 1112a574db85Sraf int 11137257d1b4Sraf waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) 1114a574db85Sraf { 1115a574db85Sraf extern int __waitid(idtype_t, id_t, siginfo_t *, int); 1116a574db85Sraf int rv; 11177c478bd9Sstevel@tonic-gate 1118a574db85Sraf if (options & WNOHANG) 1119a574db85Sraf return (__waitid(idtype, id, infop, options)); 1120a574db85Sraf PERFORM(__waitid(idtype, id, infop, options)) 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate ssize_t 11247257d1b4Sraf writev(int fildes, const struct iovec *iov, int iovcnt) 11257c478bd9Sstevel@tonic-gate { 1126a574db85Sraf extern ssize_t __writev(int, const struct iovec *, int); 11277c478bd9Sstevel@tonic-gate ssize_t rv; 11287c478bd9Sstevel@tonic-gate 1129a574db85Sraf PERFORM(__writev(fildes, iov, iovcnt)) 11307c478bd9Sstevel@tonic-gate } 1131