10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54843Sraf * Common Development and Distribution License (the "License").
64843Sraf * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
214843Sraf
220Sstevel@tonic-gate /*
236515Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include "thr_uberdata.h"
300Sstevel@tonic-gate #include "mtlib.h"
310Sstevel@tonic-gate
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate * fork handlers are run in LIFO order.
340Sstevel@tonic-gate * The libc fork handler is expected to be the first handler installed,
350Sstevel@tonic-gate * hence would be the last fork handler run in preparation for fork1().
360Sstevel@tonic-gate * It is essential that this be so, for other libraries depend on libc
370Sstevel@tonic-gate * and may grab their own locks before calling into libc. By special
380Sstevel@tonic-gate * arrangement, the loader runs libc's init section (libc_init()) first.
390Sstevel@tonic-gate */
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * pthread_atfork(): installs handlers to be called during fork1().
430Sstevel@tonic-gate * There is no POSIX API that provides for deletion of atfork handlers.
440Sstevel@tonic-gate * Collaboration between the loader and libc ensures that atfork
450Sstevel@tonic-gate * handlers installed by a library are deleted when that library
460Sstevel@tonic-gate * is unloaded (see _preexec_atfork_unload() in atexit.c).
470Sstevel@tonic-gate */
480Sstevel@tonic-gate int
pthread_atfork(void (* prepare)(void),void (* parent)(void),void (* child)(void))49*6812Sraf pthread_atfork(void (*prepare)(void),
500Sstevel@tonic-gate void (*parent)(void), void (*child)(void))
510Sstevel@tonic-gate {
520Sstevel@tonic-gate ulwp_t *self = curthread;
530Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata;
540Sstevel@tonic-gate atfork_t *atfp;
550Sstevel@tonic-gate atfork_t *head;
564843Sraf int error = 0;
570Sstevel@tonic-gate
586515Sraf (void) mutex_lock(&udp->atfork_lock);
594843Sraf if (self->ul_fork) {
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate * Cannot call pthread_atfork() from a fork handler.
620Sstevel@tonic-gate */
634843Sraf error = EDEADLK;
644843Sraf } else if ((atfp = lmalloc(sizeof (atfork_t))) == NULL) {
654843Sraf error = ENOMEM;
664843Sraf } else {
674843Sraf atfp->prepare = prepare;
684843Sraf atfp->parent = parent;
694843Sraf atfp->child = child;
704843Sraf if ((head = udp->atforklist) == NULL) {
714843Sraf udp->atforklist = atfp;
724843Sraf atfp->forw = atfp->back = atfp;
734843Sraf } else {
744843Sraf head->back->forw = atfp;
754843Sraf atfp->forw = head;
764843Sraf atfp->back = head->back;
774843Sraf head->back = atfp;
784843Sraf }
790Sstevel@tonic-gate }
804843Sraf
816515Sraf (void) mutex_unlock(&udp->atfork_lock);
824843Sraf return (error);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate * _prefork_handler() is called by fork1() before it starts processing.
870Sstevel@tonic-gate * It executes the user installed "prepare" routines in LIFO order (POSIX)
880Sstevel@tonic-gate */
890Sstevel@tonic-gate void
_prefork_handler(void)900Sstevel@tonic-gate _prefork_handler(void)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate uberdata_t *udp = curthread->ul_uberdata;
930Sstevel@tonic-gate atfork_t *atfork_q;
940Sstevel@tonic-gate atfork_t *atfp;
950Sstevel@tonic-gate
964843Sraf ASSERT(MUTEX_OWNED(&udp->atfork_lock, curthread));
970Sstevel@tonic-gate if ((atfork_q = udp->atforklist) != NULL) {
980Sstevel@tonic-gate atfp = atfork_q = atfork_q->back;
990Sstevel@tonic-gate do {
1000Sstevel@tonic-gate if (atfp->prepare)
1010Sstevel@tonic-gate (*atfp->prepare)();
1020Sstevel@tonic-gate } while ((atfp = atfp->back) != atfork_q);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate /*
1070Sstevel@tonic-gate * _postfork_parent_handler() is called by fork1() after it retuns as parent.
1080Sstevel@tonic-gate * It executes the user installed "parent" routines in FIFO order (POSIX).
1090Sstevel@tonic-gate */
1100Sstevel@tonic-gate void
_postfork_parent_handler(void)1110Sstevel@tonic-gate _postfork_parent_handler(void)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate uberdata_t *udp = curthread->ul_uberdata;
1140Sstevel@tonic-gate atfork_t *atfork_q;
1150Sstevel@tonic-gate atfork_t *atfp;
1160Sstevel@tonic-gate
1174843Sraf ASSERT(MUTEX_OWNED(&udp->atfork_lock, curthread));
1180Sstevel@tonic-gate if ((atfork_q = udp->atforklist) != NULL) {
1190Sstevel@tonic-gate atfp = atfork_q;
1200Sstevel@tonic-gate do {
1210Sstevel@tonic-gate if (atfp->parent)
1220Sstevel@tonic-gate (*atfp->parent)();
1230Sstevel@tonic-gate } while ((atfp = atfp->forw) != atfork_q);
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate /*
1280Sstevel@tonic-gate * _postfork_child_handler() is called by fork1() after it returns as child.
1290Sstevel@tonic-gate * It executes the user installed "child" routines in FIFO order (POSIX).
1300Sstevel@tonic-gate */
1310Sstevel@tonic-gate void
_postfork_child_handler(void)1320Sstevel@tonic-gate _postfork_child_handler(void)
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate uberdata_t *udp = curthread->ul_uberdata;
1350Sstevel@tonic-gate atfork_t *atfork_q;
1360Sstevel@tonic-gate atfork_t *atfp;
1370Sstevel@tonic-gate
1384843Sraf ASSERT(MUTEX_OWNED(&udp->atfork_lock, curthread));
1390Sstevel@tonic-gate if ((atfork_q = udp->atforklist) != NULL) {
1400Sstevel@tonic-gate atfp = atfork_q;
1410Sstevel@tonic-gate do {
1420Sstevel@tonic-gate if (atfp->child)
1430Sstevel@tonic-gate (*atfp->child)();
1440Sstevel@tonic-gate } while ((atfp = atfp->forw) != atfork_q);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate }
147