13235Sraf/* 23235Sraf * CDDL HEADER START 33235Sraf * 43235Sraf * The contents of this file are subject to the terms of the 53235Sraf * Common Development and Distribution License (the "License"). 63235Sraf * You may not use this file except in compliance with the License. 73235Sraf * 83235Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93235Sraf * or http://www.opensolaris.org/os/licensing. 103235Sraf * See the License for the specific language governing permissions 113235Sraf * and limitations under the License. 123235Sraf * 133235Sraf * When distributing Covered Code, include this CDDL HEADER in each 143235Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153235Sraf * If applicable, add the following below this CDDL HEADER, with the 163235Sraf * fields enclosed by brackets "[]" replaced with your own identifying 173235Sraf * information: Portions Copyright [yyyy] [name of copyright owner] 183235Sraf * 193235Sraf * CDDL HEADER END 203235Sraf */ 213235Sraf 226812Sraf/* 23*11913SRoger.Faulkner@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 246812Sraf * Use is subject to license terms. 256812Sraf */ 266812Sraf 273235Sraf/* Copyright (c) 1988 AT&T */ 283235Sraf/* All Rights Reserved */ 293235Sraf 307298SMark.J.Nelson@Sun.COM .file "vforkx.s" 313235Sraf 323235Sraf#include "SYS.h" 333235Sraf#include <assym.h> 343235Sraf 353235Sraf/* 363235Sraf * pid = vforkx(flags); 373235Sraf * syscall trap: forksys(2, flags) 383235Sraf * 393235Sraf * pid = vfork(); 403235Sraf * syscall trap: forksys(2, 0) 413235Sraf * 423235Sraf * From the syscall: 433235Sraf * %o1 == 0 in parent process, %o1 == 1 in child process. 443235Sraf * %o0 == pid of child in parent, %o0 == pid of parent in child. 453235Sraf * 463235Sraf * The child gets a zero return value. 473235Sraf * The parent gets the pid of the child. 483235Sraf */ 493235Sraf 503235Sraf/* 513235Sraf * Note that since the SPARC architecture maintains stack maintence 523235Sraf * information (return pc, sp, fp) in the register windows, both parent 533235Sraf * and child can execute in a common address space without conflict. 543235Sraf * 553235Sraf * We block all blockable signals while performing the vfork() system call 563235Sraf * trap. This enables us to set curthread->ul_vfork safely, so that we 573235Sraf * don't end up in a signal handler with curthread->ul_vfork set wrong. 583235Sraf */ 593235Sraf 603235Sraf ENTRY_NP(vforkx) 613235Sraf ba 0f 62*11913SRoger.Faulkner@Sun.COM mov %o0, %o5 /* flags */ 633235Sraf ENTRY_NP(vfork) 64*11913SRoger.Faulkner@Sun.COM clr %o5 /* flags = 0 */ 653235Sraf0: 663235Sraf mov SIG_SETMASK, %o0 /* block all signals */ 673235Sraf set MASKSET0, %o1 683235Sraf set MASKSET1, %o2 69*11913SRoger.Faulkner@Sun.COM set MASKSET2, %o3 70*11913SRoger.Faulkner@Sun.COM set MASKSET3, %o4 71*11913SRoger.Faulkner@Sun.COM SYSTRAP_RVAL1(lwp_sigmask) 723235Sraf 73*11913SRoger.Faulkner@Sun.COM mov %o5, %o1 /* flags */ 743235Sraf mov 2, %o0 753235Sraf SYSTRAP_2RVALS(forksys) /* vforkx(flags) */ 763235Sraf bcc,a,pt %icc, 1f 773235Sraf tst %o1 783235Sraf 79*11913SRoger.Faulkner@Sun.COM mov %o0, %o5 /* save the vfork() error number */ 803235Sraf 813235Sraf mov SIG_SETMASK, %o0 /* reinstate signals */ 823235Sraf ld [%g7 + UL_SIGMASK], %o1 833235Sraf ld [%g7 + UL_SIGMASK + 4], %o2 84*11913SRoger.Faulkner@Sun.COM ld [%g7 + UL_SIGMASK + 8], %o3 85*11913SRoger.Faulkner@Sun.COM ld [%g7 + UL_SIGMASK + 12], %o4 86*11913SRoger.Faulkner@Sun.COM SYSTRAP_RVAL1(lwp_sigmask) 873235Sraf 883235Sraf ba __cerror 89*11913SRoger.Faulkner@Sun.COM mov %o5, %o0 /* restore the vfork() error number */ 903235Sraf 913235Sraf1: 923235Sraf /* 933235Sraf * To determine if we are (still) a child of vfork(), the child 943235Sraf * increments curthread->ul_vfork by one and the parent decrements 953235Sraf * it by one. If the result is zero, then we are not a child of 963235Sraf * vfork(), else we are. We do this to deal with the case of 973235Sraf * a vfork() child calling vfork(). 983235Sraf */ 993235Sraf bnz,pt %icc, 2f 1003235Sraf ld [%g7 + UL_VFORK], %g1 1013235Sraf brnz,a,pt %g1, 3f /* don't let it go negative */ 1023235Sraf sub %g1, 1, %g1 /* curthread->ul_vfork--; */ 1033235Sraf ba,a 3f 1043235Sraf2: 1053235Sraf clr %o0 /* zero the return value in the child */ 1063235Sraf add %g1, 1, %g1 /* curthread->ul_vfork++; */ 1073235Sraf3: 1083235Sraf st %g1, [%g7 + UL_VFORK] 1093235Sraf /* 1103235Sraf * Clear the schedctl interface in both parent and child. 1113235Sraf * (The child might have modified the parent.) 1123235Sraf */ 1133235Sraf stn %g0, [%g7 + UL_SCHEDCTL] 1143235Sraf stn %g0, [%g7 + UL_SCHEDCTL_CALLED] 115*11913SRoger.Faulkner@Sun.COM mov %o0, %o5 /* save the vfork() return value */ 1163235Sraf 1173235Sraf mov SIG_SETMASK, %o0 /* reinstate signals */ 1183235Sraf ld [%g7 + UL_SIGMASK], %o1 1193235Sraf ld [%g7 + UL_SIGMASK + 4], %o2 120*11913SRoger.Faulkner@Sun.COM ld [%g7 + UL_SIGMASK + 8], %o3 121*11913SRoger.Faulkner@Sun.COM ld [%g7 + UL_SIGMASK + 12], %o4 122*11913SRoger.Faulkner@Sun.COM SYSTRAP_RVAL1(lwp_sigmask) 1233235Sraf 1243235Sraf retl 125*11913SRoger.Faulkner@Sun.COM mov %o5, %o0 /* restore the vfork() return value */ 1263235Sraf SET_SIZE(vfork) 1273235Sraf SET_SIZE(vforkx) 128