1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2015, Joyent, Inc. All rights reserved.
26 */
27
28 /* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
29
30 #include "lint.h"
31 #include "thr_uberdata.h"
32 #include <stdarg.h>
33 #include <poll.h>
34 #include <stropts.h>
35 #include <dlfcn.h>
36 #include <wait.h>
37 #include <sys/socket.h>
38 #include <sys/uio.h>
39 #include <sys/file.h>
40 #include <sys/door.h>
41
42 /*
43 * These leading-underbar symbols exist because mistakes were made
44 * in the past that put them into non-SUNWprivate versions of
45 * the libc mapfiles. They should be eliminated, but oh well...
46 */
47 #pragma weak _fork = fork
48 #pragma weak _read = read
49 #pragma weak _write = write
50 #pragma weak _getmsg = getmsg
51 #pragma weak _getpmsg = getpmsg
52 #pragma weak _putmsg = putmsg
53 #pragma weak _putpmsg = putpmsg
54 #pragma weak _sleep = sleep
55 #pragma weak _close = close
56 #pragma weak _creat = creat
57 #pragma weak _fcntl = fcntl
58 #pragma weak _fsync = fsync
59 #pragma weak _lockf = lockf
60 #pragma weak _msgrcv = msgrcv
61 #pragma weak _msgsnd = msgsnd
62 #pragma weak _msync = msync
63 #pragma weak _open = open
64 #pragma weak _openat = openat
65 #pragma weak _pause = pause
66 #pragma weak _readv = readv
67 #pragma weak _sigpause = sigpause
68 #pragma weak _sigsuspend = sigsuspend
69 #pragma weak _tcdrain = tcdrain
70 #pragma weak _waitid = waitid
71 #pragma weak _writev = writev
72
73 #if !defined(_LP64)
74 #pragma weak _creat64 = creat64
75 #pragma weak _lockf64 = lockf64
76 #pragma weak _open64 = open64
77 #pragma weak _openat64 = openat64
78 #pragma weak _pread64 = pread64
79 #pragma weak _pwrite64 = pwrite64
80 #endif
81
82 /*
83 * These are SUNWprivate, but they are being used by Sun Studio libcollector.
84 */
85 #pragma weak _fork1 = fork1
86 #pragma weak _forkall = forkall
87
88 /*
89 * atfork_lock protects the pthread_atfork() data structures.
90 *
91 * fork_lock does double-duty. Not only does it (and atfork_lock)
92 * serialize calls to fork() and forkall(), but it also serializes calls
93 * to thr_suspend() and thr_continue() (because fork() and forkall() also
94 * suspend and continue other threads and they want no competition).
95 *
96 * Functions called in dlopen()ed L10N objects can do anything, including
97 * call malloc() and free(). Such calls are not fork-safe when protected
98 * by an ordinary mutex that is acquired in libc's prefork processing
99 * because, with an interposed malloc library present, there would be a
100 * lock ordering violation due to the pthread_atfork() prefork function
101 * in the interposition library acquiring its malloc lock(s) before the
102 * ordinary mutex in libc being acquired by libc's prefork functions.
103 *
104 * Within libc, calls to malloc() and free() are fork-safe if the calls
105 * are made while holding no other libc locks. This covers almost all
106 * of libc's malloc() and free() calls. For those libc code paths, such
107 * as the above-mentioned L10N calls, that require serialization and that
108 * may call malloc() or free(), libc uses callout_lock_enter() to perform
109 * the serialization. This works because callout_lock is not acquired as
110 * part of running the pthread_atfork() prefork handlers (to avoid the
111 * lock ordering violation described above). Rather, it is simply
112 * reinitialized in postfork1_child() to cover the case that some
113 * now-defunct thread might have been suspended while holding it.
114 */
115
116 void
fork_lock_enter(void)117 fork_lock_enter(void)
118 {
119 ASSERT(curthread->ul_critical == 0);
120 (void) mutex_lock(&curthread->ul_uberdata->fork_lock);
121 }
122
123 void
fork_lock_exit(void)124 fork_lock_exit(void)
125 {
126 ASSERT(curthread->ul_critical == 0);
127 (void) mutex_unlock(&curthread->ul_uberdata->fork_lock);
128 }
129
130 /*
131 * Use cancel_safe_mutex_lock() to protect against being cancelled while
132 * holding callout_lock and calling outside of libc (via L10N plugins).
133 * We will honor a pending cancellation request when callout_lock_exit()
134 * is called, by calling cancel_safe_mutex_unlock().
135 */
136 void
callout_lock_enter(void)137 callout_lock_enter(void)
138 {
139 ASSERT(curthread->ul_critical == 0);
140 cancel_safe_mutex_lock(&curthread->ul_uberdata->callout_lock);
141 }
142
143 void
callout_lock_exit(void)144 callout_lock_exit(void)
145 {
146 ASSERT(curthread->ul_critical == 0);
147 cancel_safe_mutex_unlock(&curthread->ul_uberdata->callout_lock);
148 }
149
150 pid_t
forkx(int flags)151 forkx(int flags)
152 {
153 ulwp_t *self = curthread;
154 uberdata_t *udp = self->ul_uberdata;
155 pid_t pid;
156
157 if (self->ul_vfork) {
158 /*
159 * We are a child of vfork(); omit all of the fork
160 * logic and go straight to the system call trap.
161 * A vfork() child of a multithreaded parent
162 * must never call fork().
163 */
164 if (udp->uberflags.uf_mt) {
165 errno = ENOTSUP;
166 return (-1);
167 }
168 pid = __forkx(flags);
169 if (pid == 0) { /* child */
170 udp->pid = getpid();
171 self->ul_vfork = 0;
172 }
173 return (pid);
174 }
175
176 sigoff(self);
177 if (self->ul_fork) {
178 /*
179 * Cannot call fork() from a fork handler.
180 */
181 sigon(self);
182 errno = EDEADLK;
183 return (-1);
184 }
185 self->ul_fork = 1;
186
187 /*
188 * The functions registered by pthread_atfork() are defined by
189 * the application and its libraries and we must not hold any
190 * internal lmutex_lock()-acquired locks while invoking them.
191 * We hold only udp->atfork_lock to protect the atfork linkages.
192 * If one of these pthread_atfork() functions attempts to fork
193 * or to call pthread_atfork(), libc will detect the error and
194 * fail the call with EDEADLK. Otherwise, the pthread_atfork()
195 * functions are free to do anything they please (except they
196 * will not receive any signals).
197 */
198 (void) mutex_lock(&udp->atfork_lock);
199
200 /*
201 * Posix (SUSv3) requires fork() to be async-signal-safe.
202 * This cannot be made to happen with fork handlers in place
203 * (they grab locks). To be in nominal compliance, don't run
204 * any fork handlers if we are called within a signal context.
205 * This leaves the child process in a questionable state with
206 * respect to its locks, but at least the parent process does
207 * not become deadlocked due to the calling thread attempting
208 * to acquire a lock that it already owns.
209 */
210 if (self->ul_siglink == NULL)
211 _prefork_handler();
212
213 /*
214 * Block every other thread attempting thr_suspend() or thr_continue().
215 */
216 (void) mutex_lock(&udp->fork_lock);
217
218 /*
219 * Block all signals.
220 * Just deferring them via sigoff() is not enough.
221 * We have to avoid taking a deferred signal in the child
222 * that was actually sent to the parent before __forkx().
223 */
224 block_all_signals(self);
225
226 /*
227 * This suspends all threads but this one, leaving them
228 * suspended outside of any critical regions in the library.
229 * Thus, we are assured that no lmutex_lock()-acquired library
230 * locks are held while we invoke fork() from the current thread.
231 */
232 suspend_fork();
233
234 pid = __forkx(flags);
235
236 if (pid == 0) { /* child */
237 /*
238 * Clear our schedctl pointer.
239 * Discard any deferred signal that was sent to the parent.
240 * Because we blocked all signals before __forkx(), a
241 * deferred signal cannot have been taken by the child.
242 */
243 self->ul_schedctl_called = NULL;
244 self->ul_schedctl = NULL;
245 self->ul_cursig = 0;
246 self->ul_siginfo.si_signo = 0;
247 udp->pid = getpid();
248 /* reset the library's data structures to reflect one thread */
249 unregister_locks();
250 postfork1_child();
251 restore_signals(self);
252 (void) mutex_unlock(&udp->fork_lock);
253 if (self->ul_siglink == NULL)
254 _postfork_child_handler();
255 } else {
256 /* restart all threads that were suspended for fork() */
257 continue_fork(0);
258 restore_signals(self);
259 (void) mutex_unlock(&udp->fork_lock);
260 if (self->ul_siglink == NULL)
261 _postfork_parent_handler();
262 }
263
264 (void) mutex_unlock(&udp->atfork_lock);
265 self->ul_fork = 0;
266 sigon(self);
267
268 return (pid);
269 }
270
271 /*
272 * fork() is fork1() for both Posix threads and Solaris threads.
273 * The forkall() interface exists for applications that require
274 * the semantics of replicating all threads.
275 */
276 #pragma weak fork1 = fork
277 pid_t
fork(void)278 fork(void)
279 {
280 return (forkx(0));
281 }
282
283 /*
284 * Much of the logic here is the same as in forkx().
285 * See the comments in forkx(), above.
286 */
287 pid_t
forkallx(int flags)288 forkallx(int flags)
289 {
290 ulwp_t *self = curthread;
291 uberdata_t *udp = self->ul_uberdata;
292 pid_t pid;
293
294 if (self->ul_vfork) {
295 if (udp->uberflags.uf_mt) {
296 errno = ENOTSUP;
297 return (-1);
298 }
299 pid = __forkallx(flags);
300 if (pid == 0) { /* child */
301 udp->pid = getpid();
302 self->ul_vfork = 0;
303 }
304 return (pid);
305 }
306
307 sigoff(self);
308 if (self->ul_fork) {
309 sigon(self);
310 errno = EDEADLK;
311 return (-1);
312 }
313 self->ul_fork = 1;
314 (void) mutex_lock(&udp->atfork_lock);
315 (void) mutex_lock(&udp->fork_lock);
316 block_all_signals(self);
317 suspend_fork();
318
319 pid = __forkallx(flags);
320
321 if (pid == 0) {
322 self->ul_schedctl_called = NULL;
323 self->ul_schedctl = NULL;
324 self->ul_cursig = 0;
325 self->ul_siginfo.si_signo = 0;
326 udp->pid = getpid();
327 unregister_locks();
328 continue_fork(1);
329 } else {
330 continue_fork(0);
331 }
332 restore_signals(self);
333 (void) mutex_unlock(&udp->fork_lock);
334 (void) mutex_unlock(&udp->atfork_lock);
335 self->ul_fork = 0;
336 sigon(self);
337
338 return (pid);
339 }
340
341 pid_t
forkall(void)342 forkall(void)
343 {
344 return (forkallx(0));
345 }
346
347 /*
348 * For the implementation of cancellation at cancellation points.
349 */
350 #define PROLOGUE \
351 { \
352 ulwp_t *self = curthread; \
353 int nocancel = \
354 (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \
355 self->ul_critical | self->ul_sigdefer); \
356 int abort = 0; \
357 if (nocancel == 0) { \
358 self->ul_save_async = self->ul_cancel_async; \
359 if (!self->ul_cancel_disabled) { \
360 self->ul_cancel_async = 1; \
361 if (self->ul_cancel_pending) \
362 pthread_exit(PTHREAD_CANCELED); \
363 } \
364 self->ul_sp = stkptr(); \
365 } else if (self->ul_cancel_pending && \
366 !self->ul_cancel_disabled) { \
367 set_cancel_eintr_flag(self); \
368 abort = 1; \
369 }
370
371 #define EPILOGUE \
372 if (nocancel == 0) { \
373 self->ul_sp = 0; \
374 self->ul_cancel_async = self->ul_save_async; \
375 } \
376 }
377
378 /*
379 * Perform the body of the action required by most of the cancelable
380 * function calls. The return(function_call) part is to allow the
381 * compiler to make the call be executed with tail recursion, which
382 * saves a register window on sparc and slightly (not much) improves
383 * the code for x86/x64 compilations.
384 */
385 #define PERFORM(function_call) \
386 PROLOGUE \
387 if (abort) { \
388 *self->ul_errnop = EINTR; \
389 return (-1); \
390 } \
391 if (nocancel) \
392 return (function_call); \
393 rv = function_call; \
394 EPILOGUE \
395 return (rv);
396
397 /*
398 * Specialized prologue for sigsuspend() and pollsys().
399 * These system calls pass a signal mask to the kernel.
400 * The kernel replaces the thread's signal mask with the
401 * temporary mask before the thread goes to sleep. If
402 * a signal is received, the signal handler will execute
403 * with the temporary mask, as modified by the sigaction
404 * for the particular signal.
405 *
406 * We block all signals until we reach the kernel with the
407 * temporary mask. This eliminates race conditions with
408 * setting the signal mask while signals are being posted.
409 */
410 #define PROLOGUE_MASK(sigmask) \
411 { \
412 ulwp_t *self = curthread; \
413 int nocancel = \
414 (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks | \
415 self->ul_critical | self->ul_sigdefer); \
416 if (!self->ul_vfork) { \
417 if (sigmask) { \
418 block_all_signals(self); \
419 self->ul_tmpmask = *sigmask; \
420 delete_reserved_signals(&self->ul_tmpmask); \
421 self->ul_sigsuspend = 1; \
422 } \
423 if (nocancel == 0) { \
424 self->ul_save_async = self->ul_cancel_async; \
425 if (!self->ul_cancel_disabled) { \
426 self->ul_cancel_async = 1; \
427 if (self->ul_cancel_pending) { \
428 if (self->ul_sigsuspend) { \
429 self->ul_sigsuspend = 0;\
430 restore_signals(self); \
431 } \
432 pthread_exit(PTHREAD_CANCELED); \
433 } \
434 } \
435 self->ul_sp = stkptr(); \
436 } \
437 }
438
439 /*
440 * If a signal is taken, we return from the system call wrapper with
441 * our original signal mask restored (see code in call_user_handler()).
442 * If not (self->ul_sigsuspend is still non-zero), we must restore our
443 * original signal mask ourself.
444 */
445 #define EPILOGUE_MASK \
446 if (nocancel == 0) { \
447 self->ul_sp = 0; \
448 self->ul_cancel_async = self->ul_save_async; \
449 } \
450 if (self->ul_sigsuspend) { \
451 self->ul_sigsuspend = 0; \
452 restore_signals(self); \
453 } \
454 }
455
456 /*
457 * Cancellation prologue and epilogue functions,
458 * for cancellation points too complex to include here.
459 */
460 void
_cancel_prologue(void)461 _cancel_prologue(void)
462 {
463 ulwp_t *self = curthread;
464
465 self->ul_cancel_prologue =
466 (self->ul_vfork | self->ul_nocancel | self->ul_libc_locks |
467 self->ul_critical | self->ul_sigdefer) != 0;
468 if (self->ul_cancel_prologue == 0) {
469 self->ul_save_async = self->ul_cancel_async;
470 if (!self->ul_cancel_disabled) {
471 self->ul_cancel_async = 1;
472 if (self->ul_cancel_pending)
473 pthread_exit(PTHREAD_CANCELED);
474 }
475 self->ul_sp = stkptr();
476 } else if (self->ul_cancel_pending &&
477 !self->ul_cancel_disabled) {
478 set_cancel_eintr_flag(self);
479 }
480 }
481
482 void
_cancel_epilogue(void)483 _cancel_epilogue(void)
484 {
485 ulwp_t *self = curthread;
486
487 if (self->ul_cancel_prologue == 0) {
488 self->ul_sp = 0;
489 self->ul_cancel_async = self->ul_save_async;
490 }
491 }
492
493 /*
494 * Called from _thrp_join() (thr_join() is a cancellation point)
495 */
496 int
lwp_wait(thread_t tid,thread_t * found)497 lwp_wait(thread_t tid, thread_t *found)
498 {
499 int error;
500
501 PROLOGUE
502 if (abort)
503 return (EINTR);
504 while ((error = __lwp_wait(tid, found)) == EINTR && !cancel_active())
505 continue;
506 EPILOGUE
507 return (error);
508 }
509
510 ssize_t
read(int fd,void * buf,size_t size)511 read(int fd, void *buf, size_t size)
512 {
513 extern ssize_t __read(int, void *, size_t);
514 ssize_t rv;
515
516 PERFORM(__read(fd, buf, size))
517 }
518
519 ssize_t
write(int fd,const void * buf,size_t size)520 write(int fd, const void *buf, size_t size)
521 {
522 extern ssize_t __write(int, const void *, size_t);
523 ssize_t rv;
524
525 PERFORM(__write(fd, buf, size))
526 }
527
528 int
getmsg(int fd,struct strbuf * ctlptr,struct strbuf * dataptr,int * flagsp)529 getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr,
530 int *flagsp)
531 {
532 extern int __getmsg(int, struct strbuf *, struct strbuf *, int *);
533 int rv;
534
535 PERFORM(__getmsg(fd, ctlptr, dataptr, flagsp))
536 }
537
538 int
getpmsg(int fd,struct strbuf * ctlptr,struct strbuf * dataptr,int * bandp,int * flagsp)539 getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr,
540 int *bandp, int *flagsp)
541 {
542 extern int __getpmsg(int, struct strbuf *, struct strbuf *,
543 int *, int *);
544 int rv;
545
546 PERFORM(__getpmsg(fd, ctlptr, dataptr, bandp, flagsp))
547 }
548
549 int
putmsg(int fd,const struct strbuf * ctlptr,const struct strbuf * dataptr,int flags)550 putmsg(int fd, const struct strbuf *ctlptr,
551 const struct strbuf *dataptr, int flags)
552 {
553 extern int __putmsg(int, const struct strbuf *,
554 const struct strbuf *, int);
555 int rv;
556
557 PERFORM(__putmsg(fd, ctlptr, dataptr, flags))
558 }
559
560 int
__xpg4_putmsg(int fd,const struct strbuf * ctlptr,const struct strbuf * dataptr,int flags)561 __xpg4_putmsg(int fd, const struct strbuf *ctlptr,
562 const struct strbuf *dataptr, int flags)
563 {
564 extern int __putmsg(int, const struct strbuf *,
565 const struct strbuf *, int);
566 int rv;
567
568 PERFORM(__putmsg(fd, ctlptr, dataptr, flags|MSG_XPG4))
569 }
570
571 int
putpmsg(int fd,const struct strbuf * ctlptr,const struct strbuf * dataptr,int band,int flags)572 putpmsg(int fd, const struct strbuf *ctlptr,
573 const struct strbuf *dataptr, int band, int flags)
574 {
575 extern int __putpmsg(int, const struct strbuf *,
576 const struct strbuf *, int, int);
577 int rv;
578
579 PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags))
580 }
581
582 int
__xpg4_putpmsg(int fd,const struct strbuf * ctlptr,const struct strbuf * dataptr,int band,int flags)583 __xpg4_putpmsg(int fd, const struct strbuf *ctlptr,
584 const struct strbuf *dataptr, int band, int flags)
585 {
586 extern int __putpmsg(int, const struct strbuf *,
587 const struct strbuf *, int, int);
588 int rv;
589
590 PERFORM(__putpmsg(fd, ctlptr, dataptr, band, flags|MSG_XPG4))
591 }
592
593 int
nanosleep(const timespec_t * rqtp,timespec_t * rmtp)594 nanosleep(const timespec_t *rqtp, timespec_t *rmtp)
595 {
596 int error;
597
598 PROLOGUE
599 error = abort? EINTR : __nanosleep(rqtp, rmtp);
600 EPILOGUE
601 if (error) {
602 errno = error;
603 return (-1);
604 }
605 return (0);
606 }
607
608 int
clock_nanosleep(clockid_t clock_id,int flags,const timespec_t * rqtp,timespec_t * rmtp)609 clock_nanosleep(clockid_t clock_id, int flags,
610 const timespec_t *rqtp, timespec_t *rmtp)
611 {
612 timespec_t reltime;
613 hrtime_t start;
614 hrtime_t rqlapse;
615 hrtime_t lapse;
616 int error;
617
618 switch (clock_id) {
619 case CLOCK_VIRTUAL:
620 case CLOCK_PROCESS_CPUTIME_ID:
621 case CLOCK_THREAD_CPUTIME_ID:
622 return (ENOTSUP);
623 case CLOCK_REALTIME:
624 case CLOCK_HIGHRES:
625 break;
626 default:
627 return (EINVAL);
628 }
629 if (flags & TIMER_ABSTIME) {
630 abstime_to_reltime(clock_id, rqtp, &reltime);
631 rmtp = NULL;
632 } else {
633 reltime = *rqtp;
634 if (clock_id == CLOCK_HIGHRES)
635 start = gethrtime();
636 }
637 restart:
638 PROLOGUE
639 error = abort? EINTR : __nanosleep(&reltime, rmtp);
640 EPILOGUE
641 if (error == 0 && clock_id == CLOCK_HIGHRES) {
642 /*
643 * Don't return yet if we didn't really get a timeout.
644 * This can happen if we return because someone resets
645 * the system clock.
646 */
647 if (flags & TIMER_ABSTIME) {
648 if ((hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC +
649 rqtp->tv_nsec > gethrtime()) {
650 abstime_to_reltime(clock_id, rqtp, &reltime);
651 goto restart;
652 }
653 } else {
654 rqlapse = (hrtime_t)(uint32_t)rqtp->tv_sec * NANOSEC +
655 rqtp->tv_nsec;
656 lapse = gethrtime() - start;
657 if (rqlapse > lapse) {
658 hrt2ts(rqlapse - lapse, &reltime);
659 goto restart;
660 }
661 }
662 }
663 if (error == 0 && clock_id == CLOCK_REALTIME &&
664 (flags & TIMER_ABSTIME)) {
665 /*
666 * Don't return yet just because someone reset the
667 * system clock. Recompute the new relative time
668 * and reissue the nanosleep() call if necessary.
669 *
670 * Resetting the system clock causes all sorts of
671 * problems and the SUSV3 standards body should
672 * have made the behavior of clock_nanosleep() be
673 * implementation-defined in such a case rather than
674 * being specific about honoring the new system time.
675 * Standards bodies are filled with fools and idiots.
676 */
677 abstime_to_reltime(clock_id, rqtp, &reltime);
678 if (reltime.tv_sec != 0 || reltime.tv_nsec != 0)
679 goto restart;
680 }
681 return (error);
682 }
683
684 unsigned int
sleep(unsigned int sec)685 sleep(unsigned int sec)
686 {
687 unsigned int rem = 0;
688 timespec_t ts;
689 timespec_t tsr;
690
691 ts.tv_sec = (time_t)sec;
692 ts.tv_nsec = 0;
693 if (nanosleep(&ts, &tsr) == -1 && errno == EINTR) {
694 rem = (unsigned int)tsr.tv_sec;
695 if (tsr.tv_nsec >= NANOSEC / 2)
696 rem++;
697 }
698 return (rem);
699 }
700
701 int
usleep(useconds_t usec)702 usleep(useconds_t usec)
703 {
704 timespec_t ts;
705
706 ts.tv_sec = usec / MICROSEC;
707 ts.tv_nsec = (long)(usec % MICROSEC) * 1000;
708 (void) nanosleep(&ts, NULL);
709 return (0);
710 }
711
712 int
close(int fildes)713 close(int fildes)
714 {
715 extern void _aio_close(int);
716 extern int __close(int);
717 int rv;
718
719 /*
720 * If we call _aio_close() while in a critical region,
721 * we will draw an ASSERT() failure, so don't do it.
722 * No calls to close() from within libc need _aio_close();
723 * only the application's calls to close() need this,
724 * and such calls are never from a libc critical region.
725 */
726 if (curthread->ul_critical == 0)
727 _aio_close(fildes);
728 PERFORM(__close(fildes))
729 }
730
731 int
door_call(int d,door_arg_t * params)732 door_call(int d, door_arg_t *params)
733 {
734 extern int __door_call(int, door_arg_t *);
735 int rv;
736
737 PERFORM(__door_call(d, params))
738 }
739
740 int
fcntl(int fildes,int cmd,...)741 fcntl(int fildes, int cmd, ...)
742 {
743 extern int __fcntl(int, int, ...);
744 intptr_t arg;
745 int rv;
746 va_list ap;
747
748 va_start(ap, cmd);
749 arg = va_arg(ap, intptr_t);
750 va_end(ap);
751 if (cmd != F_SETLKW)
752 return (__fcntl(fildes, cmd, arg));
753 PERFORM(__fcntl(fildes, cmd, arg))
754 }
755
756 int
fdatasync(int fildes)757 fdatasync(int fildes)
758 {
759 extern int __fdsync(int, int);
760 int rv;
761
762 PERFORM(__fdsync(fildes, FDSYNC))
763 }
764
765 int
fsync(int fildes)766 fsync(int fildes)
767 {
768 extern int __fdsync(int, int);
769 int rv;
770
771 PERFORM(__fdsync(fildes, FSYNC))
772 }
773
774 int
lockf(int fildes,int function,off_t size)775 lockf(int fildes, int function, off_t size)
776 {
777 extern int __lockf(int, int, off_t);
778 int rv;
779
780 PERFORM(__lockf(fildes, function, size))
781 }
782
783 #if !defined(_LP64)
784 int
lockf64(int fildes,int function,off64_t size)785 lockf64(int fildes, int function, off64_t size)
786 {
787 extern int __lockf64(int, int, off64_t);
788 int rv;
789
790 PERFORM(__lockf64(fildes, function, size))
791 }
792 #endif /* !_LP64 */
793
794 ssize_t
msgrcv(int msqid,void * msgp,size_t msgsz,long msgtyp,int msgflg)795 msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
796 {
797 extern ssize_t __msgrcv(int, void *, size_t, long, int);
798 ssize_t rv;
799
800 PERFORM(__msgrcv(msqid, msgp, msgsz, msgtyp, msgflg))
801 }
802
803 int
msgsnd(int msqid,const void * msgp,size_t msgsz,int msgflg)804 msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
805 {
806 extern int __msgsnd(int, const void *, size_t, int);
807 int rv;
808
809 PERFORM(__msgsnd(msqid, msgp, msgsz, msgflg))
810 }
811
812 int
msync(caddr_t addr,size_t len,int flags)813 msync(caddr_t addr, size_t len, int flags)
814 {
815 extern int __msync(caddr_t, size_t, int);
816 int rv;
817
818 PERFORM(__msync(addr, len, flags))
819 }
820
821 int
openat(int fd,const char * path,int oflag,...)822 openat(int fd, const char *path, int oflag, ...)
823 {
824 mode_t mode;
825 int rv;
826 va_list ap;
827
828 va_start(ap, oflag);
829 mode = va_arg(ap, mode_t);
830 va_end(ap);
831 PERFORM(__openat(fd, path, oflag, mode))
832 }
833
834 int
open(const char * path,int oflag,...)835 open(const char *path, int oflag, ...)
836 {
837 mode_t mode;
838 int rv;
839 va_list ap;
840
841 va_start(ap, oflag);
842 mode = va_arg(ap, mode_t);
843 va_end(ap);
844 PERFORM(__open(path, oflag, mode))
845 }
846
847 int
creat(const char * path,mode_t mode)848 creat(const char *path, mode_t mode)
849 {
850 return (open(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
851 }
852
853 #if !defined(_LP64)
854 int
openat64(int fd,const char * path,int oflag,...)855 openat64(int fd, const char *path, int oflag, ...)
856 {
857 mode_t mode;
858 int rv;
859 va_list ap;
860
861 va_start(ap, oflag);
862 mode = va_arg(ap, mode_t);
863 va_end(ap);
864 PERFORM(__openat64(fd, path, oflag, mode))
865 }
866
867 int
open64(const char * path,int oflag,...)868 open64(const char *path, int oflag, ...)
869 {
870 mode_t mode;
871 int rv;
872 va_list ap;
873
874 va_start(ap, oflag);
875 mode = va_arg(ap, mode_t);
876 va_end(ap);
877 PERFORM(__open64(path, oflag, mode))
878 }
879
880 int
creat64(const char * path,mode_t mode)881 creat64(const char *path, mode_t mode)
882 {
883 return (open64(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
884 }
885 #endif /* !_LP64 */
886
887 int
pause(void)888 pause(void)
889 {
890 extern int __pause(void);
891 int rv;
892
893 PERFORM(__pause())
894 }
895
896 ssize_t
pread(int fildes,void * buf,size_t nbyte,off_t offset)897 pread(int fildes, void *buf, size_t nbyte, off_t offset)
898 {
899 extern ssize_t __pread(int, void *, size_t, off_t);
900 ssize_t rv;
901
902 PERFORM(__pread(fildes, buf, nbyte, offset))
903 }
904
905 #if !defined(_LP64)
906 ssize_t
pread64(int fildes,void * buf,size_t nbyte,off64_t offset)907 pread64(int fildes, void *buf, size_t nbyte, off64_t offset)
908 {
909 extern ssize_t __pread64(int, void *, size_t, off64_t);
910 ssize_t rv;
911
912 PERFORM(__pread64(fildes, buf, nbyte, offset))
913 }
914
915 ssize_t
preadv64(int fildes,const struct iovec * iov,int iovcnt,off64_t offset)916 preadv64(int fildes, const struct iovec *iov, int iovcnt, off64_t offset)
917 {
918
919 extern ssize_t __preadv64(int, const struct iovec *, int, off_t, off_t);
920 ssize_t rv;
921
922 PERFORM(__preadv64(fildes, iov, iovcnt, offset & 0xffffffffULL,
923 offset>>32))
924 }
925 #endif /* !_LP64 */
926
927 ssize_t
preadv(int fildes,const struct iovec * iov,int iovcnt,off_t offset)928 preadv(int fildes, const struct iovec *iov, int iovcnt, off_t offset)
929 {
930
931 extern ssize_t __preadv(int, const struct iovec *, int, off_t, off_t);
932 ssize_t rv;
933
934 PERFORM(__preadv(fildes, iov, iovcnt, offset, 0))
935 }
936 ssize_t
pwrite(int fildes,const void * buf,size_t nbyte,off_t offset)937 pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
938 {
939 extern ssize_t __pwrite(int, const void *, size_t, off_t);
940 ssize_t rv;
941
942 PERFORM(__pwrite(fildes, buf, nbyte, offset))
943 }
944
945 #if !defined(_LP64)
946 ssize_t
pwrite64(int fildes,const void * buf,size_t nbyte,off64_t offset)947 pwrite64(int fildes, const void *buf, size_t nbyte, off64_t offset)
948 {
949 extern ssize_t __pwrite64(int, const void *, size_t, off64_t);
950 ssize_t rv;
951
952 PERFORM(__pwrite64(fildes, buf, nbyte, offset))
953 }
954
955 ssize_t
pwritev64(int fildes,const struct iovec * iov,int iovcnt,off64_t offset)956 pwritev64(int fildes, const struct iovec *iov, int iovcnt, off64_t offset)
957 {
958
959 extern ssize_t __pwritev64(int,
960 const struct iovec *, int, off_t, off_t);
961 ssize_t rv;
962
963 PERFORM(__pwritev64(fildes, iov, iovcnt, offset &
964 0xffffffffULL, offset>>32))
965 }
966
967 #endif /* !_LP64 */
968
969 ssize_t
pwritev(int fildes,const struct iovec * iov,int iovcnt,off_t offset)970 pwritev(int fildes, const struct iovec *iov, int iovcnt, off_t offset)
971 {
972 extern ssize_t __pwritev(int, const struct iovec *, int, off_t, off_t);
973 ssize_t rv;
974
975 PERFORM(__pwritev(fildes, iov, iovcnt, offset, 0))
976 }
977
978 ssize_t
readv(int fildes,const struct iovec * iov,int iovcnt)979 readv(int fildes, const struct iovec *iov, int iovcnt)
980 {
981 extern ssize_t __readv(int, const struct iovec *, int);
982 ssize_t rv;
983
984 PERFORM(__readv(fildes, iov, iovcnt))
985 }
986
987 int
sigpause(int sig)988 sigpause(int sig)
989 {
990 extern int __sigpause(int);
991 int rv;
992
993 PERFORM(__sigpause(sig))
994 }
995
996 int
sigsuspend(const sigset_t * set)997 sigsuspend(const sigset_t *set)
998 {
999 extern int __sigsuspend(const sigset_t *);
1000 int rv;
1001
1002 PROLOGUE_MASK(set)
1003 rv = __sigsuspend(set);
1004 EPILOGUE_MASK
1005 return (rv);
1006 }
1007
1008 int
_pollsys(struct pollfd * fds,nfds_t nfd,const timespec_t * timeout,const sigset_t * sigmask)1009 _pollsys(struct pollfd *fds, nfds_t nfd, const timespec_t *timeout,
1010 const sigset_t *sigmask)
1011 {
1012 extern int __pollsys(struct pollfd *, nfds_t, const timespec_t *,
1013 const sigset_t *);
1014 int rv;
1015
1016 PROLOGUE_MASK(sigmask)
1017 rv = __pollsys(fds, nfd, timeout, sigmask);
1018 EPILOGUE_MASK
1019 return (rv);
1020 }
1021
1022 int
sigtimedwait(const sigset_t * set,siginfo_t * infop,const timespec_t * timeout)1023 sigtimedwait(const sigset_t *set, siginfo_t *infop, const timespec_t *timeout)
1024 {
1025 extern int __sigtimedwait(const sigset_t *, siginfo_t *,
1026 const timespec_t *);
1027 siginfo_t info;
1028 int sig;
1029
1030 PROLOGUE
1031 if (abort) {
1032 *self->ul_errnop = EINTR;
1033 sig = -1;
1034 } else {
1035 sig = __sigtimedwait(set, &info, timeout);
1036 if (sig == SIGCANCEL &&
1037 (SI_FROMKERNEL(&info) || info.si_code == SI_LWP)) {
1038 do_sigcancel();
1039 *self->ul_errnop = EINTR;
1040 sig = -1;
1041 }
1042 }
1043 EPILOGUE
1044 if (sig != -1 && infop)
1045 (void) memcpy(infop, &info, sizeof (*infop));
1046 return (sig);
1047 }
1048
1049 int
sigwait(sigset_t * set)1050 sigwait(sigset_t *set)
1051 {
1052 return (sigtimedwait(set, NULL, NULL));
1053 }
1054
1055 int
sigwaitinfo(const sigset_t * set,siginfo_t * info)1056 sigwaitinfo(const sigset_t *set, siginfo_t *info)
1057 {
1058 return (sigtimedwait(set, info, NULL));
1059 }
1060
1061 int
sigqueue(pid_t pid,int signo,const union sigval value)1062 sigqueue(pid_t pid, int signo, const union sigval value)
1063 {
1064 extern int __sigqueue(pid_t pid, int signo,
1065 /* const union sigval */ void *value, int si_code, int block);
1066 return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE, 0));
1067 }
1068
1069 int
_so_accept(int sock,struct sockaddr * addr,uint_t * addrlen,int version,int flags)1070 _so_accept(int sock, struct sockaddr *addr, uint_t *addrlen, int version,
1071 int flags)
1072 {
1073 extern int __so_accept(int, struct sockaddr *, uint_t *, int, int);
1074 int rv;
1075
1076 PERFORM(__so_accept(sock, addr, addrlen, version, flags))
1077 }
1078
1079 int
_so_connect(int sock,struct sockaddr * addr,uint_t addrlen,int version)1080 _so_connect(int sock, struct sockaddr *addr, uint_t addrlen, int version)
1081 {
1082 extern int __so_connect(int, struct sockaddr *, uint_t, int);
1083 int rv;
1084
1085 PERFORM(__so_connect(sock, addr, addrlen, version))
1086 }
1087
1088 int
_so_recv(int sock,void * buf,size_t len,int flags)1089 _so_recv(int sock, void *buf, size_t len, int flags)
1090 {
1091 extern int __so_recv(int, void *, size_t, int);
1092 int rv;
1093
1094 PERFORM(__so_recv(sock, buf, len, flags))
1095 }
1096
1097 int
_so_recvfrom(int sock,void * buf,size_t len,int flags,struct sockaddr * addr,int * addrlen)1098 _so_recvfrom(int sock, void *buf, size_t len, int flags,
1099 struct sockaddr *addr, int *addrlen)
1100 {
1101 extern int __so_recvfrom(int, void *, size_t, int,
1102 struct sockaddr *, int *);
1103 int rv;
1104
1105 PERFORM(__so_recvfrom(sock, buf, len, flags, addr, addrlen))
1106 }
1107
1108 int
_so_recvmsg(int sock,struct msghdr * msg,int flags)1109 _so_recvmsg(int sock, struct msghdr *msg, int flags)
1110 {
1111 extern int __so_recvmsg(int, struct msghdr *, int);
1112 int rv;
1113
1114 PERFORM(__so_recvmsg(sock, msg, flags))
1115 }
1116
1117 int
_so_send(int sock,const void * buf,size_t len,int flags)1118 _so_send(int sock, const void *buf, size_t len, int flags)
1119 {
1120 extern int __so_send(int, const void *, size_t, int);
1121 int rv;
1122
1123 PERFORM(__so_send(sock, buf, len, flags))
1124 }
1125
1126 int
_so_sendmsg(int sock,const struct msghdr * msg,int flags)1127 _so_sendmsg(int sock, const struct msghdr *msg, int flags)
1128 {
1129 extern int __so_sendmsg(int, const struct msghdr *, int);
1130 int rv;
1131
1132 PERFORM(__so_sendmsg(sock, msg, flags))
1133 }
1134
1135 int
_so_sendto(int sock,const void * buf,size_t len,int flags,const struct sockaddr * addr,int * addrlen)1136 _so_sendto(int sock, const void *buf, size_t len, int flags,
1137 const struct sockaddr *addr, int *addrlen)
1138 {
1139 extern int __so_sendto(int, const void *, size_t, int,
1140 const struct sockaddr *, int *);
1141 int rv;
1142
1143 PERFORM(__so_sendto(sock, buf, len, flags, addr, addrlen))
1144 }
1145
1146 int
tcdrain(int fildes)1147 tcdrain(int fildes)
1148 {
1149 extern int __tcdrain(int);
1150 int rv;
1151
1152 PERFORM(__tcdrain(fildes))
1153 }
1154
1155 int
waitid(idtype_t idtype,id_t id,siginfo_t * infop,int options)1156 waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
1157 {
1158 extern int __waitid(idtype_t, id_t, siginfo_t *, int);
1159 int rv;
1160
1161 if (options & WNOHANG)
1162 return (__waitid(idtype, id, infop, options));
1163 PERFORM(__waitid(idtype, id, infop, options))
1164 }
1165
1166 ssize_t
writev(int fildes,const struct iovec * iov,int iovcnt)1167 writev(int fildes, const struct iovec *iov, int iovcnt)
1168 {
1169 extern ssize_t __writev(int, const struct iovec *, int);
1170 ssize_t rv;
1171
1172 PERFORM(__writev(fildes, iov, iovcnt))
1173 }
1174