1657b1f3dSraf/* 2657b1f3dSraf * CDDL HEADER START 3657b1f3dSraf * 4657b1f3dSraf * The contents of this file are subject to the terms of the 5657b1f3dSraf * Common Development and Distribution License (the "License"). 6657b1f3dSraf * You may not use this file except in compliance with the License. 7657b1f3dSraf * 8657b1f3dSraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9657b1f3dSraf * or http://www.opensolaris.org/os/licensing. 10657b1f3dSraf * See the License for the specific language governing permissions 11657b1f3dSraf * and limitations under the License. 12657b1f3dSraf * 13657b1f3dSraf * When distributing Covered Code, include this CDDL HEADER in each 14657b1f3dSraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15657b1f3dSraf * If applicable, add the following below this CDDL HEADER, with the 16657b1f3dSraf * fields enclosed by brackets "[]" replaced with your own identifying 17657b1f3dSraf * information: Portions Copyright [yyyy] [name of copyright owner] 18657b1f3dSraf * 19657b1f3dSraf * CDDL HEADER END 20657b1f3dSraf */ 21657b1f3dSraf 22657b1f3dSraf/* 23*bdf0047cSRoger A. Faulkner * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24657b1f3dSraf * Use is subject to license terms. 25657b1f3dSraf */ 26657b1f3dSraf 277257d1b4Sraf/* Copyright (c) 1988 AT&T */ 287257d1b4Sraf/* All Rights Reserved */ 297257d1b4Sraf 309a70fc3bSMark J. Nelson .file "vforkx.s" 31657b1f3dSraf 32657b1f3dSraf#include "SYS.h" 33657b1f3dSraf#include <assym.h> 34657b1f3dSraf 35657b1f3dSraf/* 36657b1f3dSraf * pid = vforkx(flags); 37657b1f3dSraf * syscall trap: forksys(2, flags) 38657b1f3dSraf * 39657b1f3dSraf * pid = vfork(); 40657b1f3dSraf * syscall trap: forksys(2, 0) 41657b1f3dSraf * 42657b1f3dSraf * From the syscall: 43657b1f3dSraf * %o1 == 0 in parent process, %o1 == 1 in child process. 44657b1f3dSraf * %o0 == pid of child in parent, %o0 == pid of parent in child. 45657b1f3dSraf * 46657b1f3dSraf * The child gets a zero return value. 47657b1f3dSraf * The parent gets the pid of the child. 48657b1f3dSraf */ 49657b1f3dSraf 50657b1f3dSraf/* 51657b1f3dSraf * Note that since the SPARC architecture maintains stack maintence 52657b1f3dSraf * information (return pc, sp, fp) in the register windows, both parent 53657b1f3dSraf * and child can execute in a common address space without conflict. 54657b1f3dSraf * 55657b1f3dSraf * We block all blockable signals while performing the vfork() system call 56657b1f3dSraf * trap. This enables us to set curthread->ul_vfork safely, so that we 57657b1f3dSraf * don't end up in a signal handler with curthread->ul_vfork set wrong. 58657b1f3dSraf */ 59657b1f3dSraf 60657b1f3dSraf ENTRY_NP(vforkx) 61657b1f3dSraf ba 0f 62*bdf0047cSRoger A. Faulkner mov %o0, %o5 /* flags */ 63657b1f3dSraf ENTRY_NP(vfork) 64*bdf0047cSRoger A. Faulkner clr %o5 /* flags = 0 */ 65657b1f3dSraf0: 66657b1f3dSraf mov SIG_SETMASK, %o0 /* block all signals */ 67657b1f3dSraf set MASKSET0, %o1 68657b1f3dSraf set MASKSET1, %o2 69*bdf0047cSRoger A. Faulkner set MASKSET2, %o3 70*bdf0047cSRoger A. Faulkner set MASKSET3, %o4 71*bdf0047cSRoger A. Faulkner SYSTRAP_RVAL1(lwp_sigmask) 72657b1f3dSraf 73*bdf0047cSRoger A. Faulkner mov %o5, %o1 /* flags */ 74657b1f3dSraf mov 2, %o0 75657b1f3dSraf SYSTRAP_2RVALS(forksys) /* vforkx(flags) */ 76657b1f3dSraf bcc,a,pt %icc, 1f 77657b1f3dSraf tst %o1 78657b1f3dSraf 79*bdf0047cSRoger A. Faulkner mov %o0, %o5 /* save the vfork() error number */ 80657b1f3dSraf 81657b1f3dSraf mov SIG_SETMASK, %o0 /* reinstate signals */ 82657b1f3dSraf ld [%g7 + UL_SIGMASK], %o1 83657b1f3dSraf ld [%g7 + UL_SIGMASK + 4], %o2 84*bdf0047cSRoger A. Faulkner ld [%g7 + UL_SIGMASK + 8], %o3 85*bdf0047cSRoger A. Faulkner ld [%g7 + UL_SIGMASK + 12], %o4 86*bdf0047cSRoger A. Faulkner SYSTRAP_RVAL1(lwp_sigmask) 87657b1f3dSraf 88657b1f3dSraf ba __cerror 89*bdf0047cSRoger A. Faulkner mov %o5, %o0 /* restore the vfork() error number */ 90657b1f3dSraf 91657b1f3dSraf1: 92657b1f3dSraf /* 93657b1f3dSraf * To determine if we are (still) a child of vfork(), the child 94657b1f3dSraf * increments curthread->ul_vfork by one and the parent decrements 95657b1f3dSraf * it by one. If the result is zero, then we are not a child of 96657b1f3dSraf * vfork(), else we are. We do this to deal with the case of 97657b1f3dSraf * a vfork() child calling vfork(). 98657b1f3dSraf */ 99657b1f3dSraf bnz,pt %icc, 2f 100657b1f3dSraf ld [%g7 + UL_VFORK], %g1 101657b1f3dSraf brnz,a,pt %g1, 3f /* don't let it go negative */ 102657b1f3dSraf sub %g1, 1, %g1 /* curthread->ul_vfork--; */ 103657b1f3dSraf ba,a 3f 104657b1f3dSraf2: 105657b1f3dSraf clr %o0 /* zero the return value in the child */ 106657b1f3dSraf add %g1, 1, %g1 /* curthread->ul_vfork++; */ 107657b1f3dSraf3: 108657b1f3dSraf st %g1, [%g7 + UL_VFORK] 109657b1f3dSraf /* 110657b1f3dSraf * Clear the schedctl interface in both parent and child. 111657b1f3dSraf * (The child might have modified the parent.) 112657b1f3dSraf */ 113657b1f3dSraf stn %g0, [%g7 + UL_SCHEDCTL] 114657b1f3dSraf stn %g0, [%g7 + UL_SCHEDCTL_CALLED] 115*bdf0047cSRoger A. Faulkner mov %o0, %o5 /* save the vfork() return value */ 116657b1f3dSraf 117657b1f3dSraf mov SIG_SETMASK, %o0 /* reinstate signals */ 118657b1f3dSraf ld [%g7 + UL_SIGMASK], %o1 119657b1f3dSraf ld [%g7 + UL_SIGMASK + 4], %o2 120*bdf0047cSRoger A. Faulkner ld [%g7 + UL_SIGMASK + 8], %o3 121*bdf0047cSRoger A. Faulkner ld [%g7 + UL_SIGMASK + 12], %o4 122*bdf0047cSRoger A. Faulkner SYSTRAP_RVAL1(lwp_sigmask) 123657b1f3dSraf 124657b1f3dSraf retl 125*bdf0047cSRoger A. Faulkner mov %o5, %o0 /* restore the vfork() return value */ 126657b1f3dSraf SET_SIZE(vfork) 127657b1f3dSraf SET_SIZE(vforkx) 128