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 223235Sraf/* 23*11913SRoger.Faulkner@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 243235Sraf * Use is subject to license terms. 253235Sraf */ 263235Sraf 277298SMark.J.Nelson@Sun.COM .file "vforkx.s" 283235Sraf 293235Sraf#include "SYS.h" 303235Sraf#include <assym.h> 313235Sraf 323235Sraf/* 333235Sraf * pid = vforkx(flags); 343235Sraf * syscall trap: forksys(2, flags) 353235Sraf * 363235Sraf * pid = vfork(); 373235Sraf * syscall trap: forksys(2, 0) 383235Sraf * 393235Sraf * From the syscall: 403235Sraf * %edx == 0 in parent process, %edx = 1 in child process. 413235Sraf * %eax == pid of child in parent, %eax == pid of parent in child. 423235Sraf * 433235Sraf * The child gets a zero return value. 443235Sraf * The parent gets the pid of the child. 453235Sraf */ 463235Sraf 473235Sraf/* 483235Sraf * The child of vfork() will execute in the parent's address space, 493235Sraf * thereby changing the stack before the parent runs again. 503235Sraf * Therefore we have to be careful how we return from vfork(). 513235Sraf * Pity the poor debugger developer who has to deal with this kludge. 523235Sraf * 533235Sraf * We block all blockable signals while performing the vfork() system call 543235Sraf * trap. This enables us to set curthread->ul_vfork safely, so that we 553235Sraf * don't end up in a signal handler with curthread->ul_vfork set wrong. 563235Sraf */ 573235Sraf 583235Sraf ENTRY_NP(vforkx) 593235Sraf movl 4(%esp), %eax /* flags */ 603235Sraf jmp 0f 613235Sraf ENTRY_NP(vfork) 623235Sraf xorl %eax, %eax /* flags = 0 */ 633235Sraf0: 643235Sraf popl %ecx /* save return %eip in %ecx */ 653235Sraf pushl %eax /* flags */ 66*11913SRoger.Faulkner@Sun.COM pushl $MASKSET3 /* block all signals */ 67*11913SRoger.Faulkner@Sun.COM pushl $MASKSET2 68*11913SRoger.Faulkner@Sun.COM pushl $MASKSET1 693235Sraf pushl $MASKSET0 703235Sraf pushl $SIG_SETMASK 713235Sraf pushl %ecx 723235Sraf __SYSCALLINT(lwp_sigmask) 73*11913SRoger.Faulkner@Sun.COM addl $24, %esp 743235Sraf 753235Sraf pushl $2 763235Sraf pushl %ecx 773235Sraf __SYSCALLINT(forksys) /* vforkx(flags) */ 783235Sraf jae 1f 793235Sraf 803235Sraf /* reconstruct stack before jumping to __cerror */ 813235Sraf addl $12, %esp 823235Sraf pushl %ecx 833235Sraf pushl %eax /* save the vfork() error number */ 843235Sraf 85*11913SRoger.Faulkner@Sun.COM pushl %gs:UL_SIGMASK+12 /* reinstate signals */ 86*11913SRoger.Faulkner@Sun.COM pushl %gs:UL_SIGMASK+8 87*11913SRoger.Faulkner@Sun.COM pushl %gs:UL_SIGMASK+4 883235Sraf pushl %gs:UL_SIGMASK 893235Sraf pushl $SIG_SETMASK 903235Sraf pushl %ecx 913235Sraf __SYSCALLINT(lwp_sigmask) 92*11913SRoger.Faulkner@Sun.COM addl $24, %esp 933235Sraf 943235Sraf popl %eax /* restore the vfork() error number */ 953235Sraf jmp __cerror 963235Sraf 973235Sraf1: 983235Sraf addl $12, %esp 993235Sraf /* 1003235Sraf * To determine if we are (still) a child of vfork(), the child 1013235Sraf * increments curthread->ul_vfork by one and the parent decrements 1023235Sraf * it by one. If the result is zero, then we are not a child of 1033235Sraf * vfork(), else we are. We do this to deal with the case of 1043235Sraf * a vfork() child calling vfork(). 1053235Sraf */ 1063235Sraf cmpl $0, %edx 1073235Sraf jne 2f 1083235Sraf movl %gs:UL_VFORK, %edx 1093235Sraf cmpl $0, %edx /* don't let it go negative */ 1103235Sraf je 3f 1113235Sraf subl $1, %edx /* curthread->ul_vfork--; */ 1123235Sraf jmp 3f 1133235Sraf2: 1143235Sraf xorl %eax, %eax /* zero the return value in the child */ 1153235Sraf movl %gs:UL_VFORK, %edx 1163235Sraf addl $1, %edx /* curthread->ul_vfork++; */ 1173235Sraf3: 1183235Sraf movl %edx, %gs:UL_VFORK 1193235Sraf /* 1203235Sraf * Clear the schedctl interface in both parent and child. 1213235Sraf * (The child might have modified the parent.) 1223235Sraf */ 1233235Sraf xorl %edx, %edx 1243235Sraf movl %edx, %gs:UL_SCHEDCTL 1253235Sraf movl %edx, %gs:UL_SCHEDCTL_CALLED 1263235Sraf pushl %eax /* save the vfork() return value */ 1273235Sraf 128*11913SRoger.Faulkner@Sun.COM pushl %gs:UL_SIGMASK+12 /* reinstate signals */ 129*11913SRoger.Faulkner@Sun.COM pushl %gs:UL_SIGMASK+8 130*11913SRoger.Faulkner@Sun.COM pushl %gs:UL_SIGMASK+4 1313235Sraf pushl %gs:UL_SIGMASK 1323235Sraf pushl $SIG_SETMASK 1333235Sraf pushl %ecx 1343235Sraf __SYSCALLINT(lwp_sigmask) 135*11913SRoger.Faulkner@Sun.COM addl $24, %esp 1363235Sraf 1373235Sraf popl %eax /* restore the vfork() return value */ 1383235Sraf jmp *%ecx /* jump back to the caller */ 1393235Sraf SET_SIZE(vfork) 1403235Sraf SET_SIZE(vforkx) 141