xref: /titanic_50/usr/src/lib/libc/sparc/sys/vforkx.s (revision bdf0047c9427cca40961a023475891c898579c37)
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