xref: /onnv-gate/usr/src/lib/libc/sparc/sys/vforkx.s (revision 3235:9af05252020c)
1*3235Sraf/*
2*3235Sraf * CDDL HEADER START
3*3235Sraf *
4*3235Sraf * The contents of this file are subject to the terms of the
5*3235Sraf * Common Development and Distribution License (the "License").
6*3235Sraf * You may not use this file except in compliance with the License.
7*3235Sraf *
8*3235Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3235Sraf * or http://www.opensolaris.org/os/licensing.
10*3235Sraf * See the License for the specific language governing permissions
11*3235Sraf * and limitations under the License.
12*3235Sraf *
13*3235Sraf * When distributing Covered Code, include this CDDL HEADER in each
14*3235Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3235Sraf * If applicable, add the following below this CDDL HEADER, with the
16*3235Sraf * fields enclosed by brackets "[]" replaced with your own identifying
17*3235Sraf * information: Portions Copyright [yyyy] [name of copyright owner]
18*3235Sraf *
19*3235Sraf * CDDL HEADER END
20*3235Sraf */
21*3235Sraf
22*3235Sraf/*	Copyright (c) 1988 AT&T	*/
23*3235Sraf/*	  All Rights Reserved	*/
24*3235Sraf
25*3235Sraf/*
26*3235Sraf * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
27*3235Sraf * Use is subject to license terms.
28*3235Sraf */
29*3235Sraf
30*3235Sraf#pragma ident	"%Z%%M%	%I%	%E% SMI"
31*3235Sraf
32*3235Sraf	.file	"%M%"
33*3235Sraf
34*3235Sraf#include <sys/asm_linkage.h>
35*3235Sraf
36*3235Sraf	ANSI_PRAGMA_WEAK(vforkx,function)
37*3235Sraf	ANSI_PRAGMA_WEAK(vfork,function)
38*3235Sraf
39*3235Sraf#include "SYS.h"
40*3235Sraf#include <assym.h>
41*3235Sraf
42*3235Sraf/*
43*3235Sraf * pid = vforkx(flags);
44*3235Sraf * syscall trap: forksys(2, flags)
45*3235Sraf *
46*3235Sraf * pid = vfork();
47*3235Sraf * syscall trap: forksys(2, 0)
48*3235Sraf *
49*3235Sraf * From the syscall:
50*3235Sraf * %o1 == 0 in parent process, %o1 == 1 in child process.
51*3235Sraf * %o0 == pid of child in parent, %o0 == pid of parent in child.
52*3235Sraf *
53*3235Sraf * The child gets a zero return value.
54*3235Sraf * The parent gets the pid of the child.
55*3235Sraf */
56*3235Sraf
57*3235Sraf/*
58*3235Sraf * Note that since the SPARC architecture maintains stack maintence
59*3235Sraf * information (return pc, sp, fp) in the register windows, both parent
60*3235Sraf * and child can execute in a common address space without conflict.
61*3235Sraf *
62*3235Sraf * We block all blockable signals while performing the vfork() system call
63*3235Sraf * trap.  This enables us to set curthread->ul_vfork safely, so that we
64*3235Sraf * don't end up in a signal handler with curthread->ul_vfork set wrong.
65*3235Sraf */
66*3235Sraf
67*3235Sraf	ENTRY_NP(vforkx)
68*3235Sraf	ba	0f
69*3235Sraf	mov	%o0, %o3		/* flags */
70*3235Sraf	ENTRY_NP(vfork)
71*3235Sraf	clr	%o3			/* flags = 0 */
72*3235Sraf0:
73*3235Sraf	mov	SIG_SETMASK, %o0	/* block all signals */
74*3235Sraf	set	MASKSET0, %o1
75*3235Sraf	set	MASKSET1, %o2
76*3235Sraf	SYSTRAP_2RVALS(lwp_sigmask)
77*3235Sraf
78*3235Sraf	mov	%o3, %o1		/* flags */
79*3235Sraf	mov	2, %o0
80*3235Sraf	SYSTRAP_2RVALS(forksys)		/* vforkx(flags) */
81*3235Sraf	bcc,a,pt %icc, 1f
82*3235Sraf	tst	%o1
83*3235Sraf
84*3235Sraf	mov	%o0, %o3		/* save the vfork() error number */
85*3235Sraf
86*3235Sraf	mov	SIG_SETMASK, %o0	/* reinstate signals */
87*3235Sraf	ld	[%g7 + UL_SIGMASK], %o1
88*3235Sraf	ld	[%g7 + UL_SIGMASK + 4], %o2
89*3235Sraf	SYSTRAP_2RVALS(lwp_sigmask)
90*3235Sraf
91*3235Sraf	ba	__cerror
92*3235Sraf	mov	%o3, %o0		/* restore the vfork() error number */
93*3235Sraf
94*3235Sraf1:
95*3235Sraf	/*
96*3235Sraf	 * To determine if we are (still) a child of vfork(), the child
97*3235Sraf	 * increments curthread->ul_vfork by one and the parent decrements
98*3235Sraf	 * it by one.  If the result is zero, then we are not a child of
99*3235Sraf	 * vfork(), else we are.  We do this to deal with the case of
100*3235Sraf	 * a vfork() child calling vfork().
101*3235Sraf	 */
102*3235Sraf	bnz,pt	%icc, 2f
103*3235Sraf	ld	[%g7 + UL_VFORK], %g1
104*3235Sraf	brnz,a,pt %g1, 3f		/* don't let it go negative */
105*3235Sraf	sub	%g1, 1, %g1		/* curthread->ul_vfork--; */
106*3235Sraf	ba,a	3f
107*3235Sraf2:
108*3235Sraf	clr	%o0			/* zero the return value in the child */
109*3235Sraf	add	%g1, 1, %g1		/* curthread->ul_vfork++; */
110*3235Sraf3:
111*3235Sraf	st	%g1, [%g7 + UL_VFORK]
112*3235Sraf	/*
113*3235Sraf	 * Clear the schedctl interface in both parent and child.
114*3235Sraf	 * (The child might have modified the parent.)
115*3235Sraf	 */
116*3235Sraf	stn	%g0, [%g7 + UL_SCHEDCTL]
117*3235Sraf	stn	%g0, [%g7 + UL_SCHEDCTL_CALLED]
118*3235Sraf	mov	%o0, %o3		/* save the vfork() return value */
119*3235Sraf
120*3235Sraf	mov	SIG_SETMASK, %o0	/* reinstate signals */
121*3235Sraf	ld	[%g7 + UL_SIGMASK], %o1
122*3235Sraf	ld	[%g7 + UL_SIGMASK + 4], %o2
123*3235Sraf	SYSTRAP_2RVALS(lwp_sigmask)
124*3235Sraf
125*3235Sraf	retl
126*3235Sraf	mov	%o3, %o0		/* restore the vfork() return value */
127*3235Sraf	SET_SIZE(vfork)
128*3235Sraf	SET_SIZE(vforkx)
129