xref: /illumos-gate/usr/src/lib/libc/i386/gen/makectxt.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*	Copyright (c) 1988 AT&T	*/
30 /*	  All Rights Reserved  	*/
31 
32 
33 #pragma weak makecontext = _makecontext
34 
35 #include "synonyms.h"
36 #include <stdarg.h>
37 #include <ucontext.h>
38 #include <sys/stack.h>
39 
40 /*
41  * The ucontext_t that the user passes in must have been primed with a
42  * call to getcontext(2), have the uc_stack member set to reflect the
43  * stack which this context will use, and have the uc_link member set
44  * to the context which should be resumed when this context returns.
45  * When makecontext() returns, the ucontext_t will be set to run the
46  * given function with the given parameters on the stack specified by
47  * uc_stack, and which will return to the ucontext_t specified by uc_link.
48  */
49 
50 static void resumecontext(void);
51 
52 void
53 makecontext(ucontext_t *ucp, void (*func)(), int argc, ...)
54 {
55 	long *sp;
56 	long *tsp;
57 	va_list ap;
58 	size_t size;
59 
60 	ucp->uc_mcontext.gregs[EIP] = (greg_t)func;
61 
62 	size = sizeof (long) * (argc + 1);
63 
64 	sp = (long *)(((uintptr_t)ucp->uc_stack.ss_sp +
65 	    ucp->uc_stack.ss_size - size) & ~(STACK_ALIGN - 1));
66 
67 	tsp = sp + 1;
68 
69 	va_start(ap, argc);
70 
71 	while (argc-- > 0) {
72 		*tsp++ = va_arg(ap, long);
73 	}
74 
75 	va_end(ap);
76 
77 	*sp = (long)resumecontext;		/* return address */
78 
79 	ucp->uc_mcontext.gregs[UESP] = (greg_t)sp;
80 }
81 
82 
83 static void
84 resumecontext(void)
85 {
86 	ucontext_t uc;
87 
88 	(void) getcontext(&uc);
89 	(void) setcontext(uc.uc_link);
90 }
91