4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
27 #include "thr_uberdata.h"
32 extern int getlwpstatus(thread_t
, lwpstatus_t
*);
33 extern int putlwpregs(thread_t
, prgregset_t
);
37 setup_top_frame(void *stk
, size_t stksize
, ulwp_t
*ulwp
)
47 * Top-of-stack must be rounded down to STACK_ALIGN and
48 * there must be a minimum frame.
50 stack
= (uint64_t *)(((uintptr_t)stk
+ stksize
) & ~(STACK_ALIGN
-1));
53 * This will return NULL if the kernel cannot allocate
54 * a page for the top page of the stack. This will cause
55 * thr_create(), pthread_create() or pthread_attr_setstack()
56 * to fail, passing the problem up to the application.
61 frame
.rpc
= (uint64_t)_lwp_start
;
62 if (uucopy(&frame
, stack
, sizeof (frame
)) == 0)
68 setup_context(ucontext_t
*ucp
, void *(*func
)(ulwp_t
*),
69 ulwp_t
*ulwp
, caddr_t stk
, size_t stksize
)
73 /* clear the context */
74 (void) memset(ucp
, 0, sizeof (*ucp
));
76 /* setup to store the current thread pointer in %fs */
77 ucp
->uc_mcontext
.gregs
[REG_FSBASE
] = (greg_t
)ulwp
;
78 ucp
->uc_mcontext
.gregs
[REG_FS
] = 0; /* null selector indicates fsbase */
80 /* all contexts should have a valid data segment descriptor for %ss */
81 ucp
->uc_mcontext
.gregs
[REG_SS
] = UDS_SEL
;
84 * Setup the top stack frame.
85 * If this fails, pass the problem up to the application.
87 if ((stack
= setup_top_frame(stk
, stksize
, ulwp
)) == NULL
)
90 /* fill in registers of interest */
91 ucp
->uc_flags
|= UC_CPU
;
92 ucp
->uc_mcontext
.gregs
[REG_RDI
] = (greg_t
)ulwp
;
93 ucp
->uc_mcontext
.gregs
[REG_RIP
] = (greg_t
)func
;
94 ucp
->uc_mcontext
.gregs
[REG_RSP
] = (greg_t
)stack
;
95 ucp
->uc_mcontext
.gregs
[REG_RBP
] = (greg_t
)(stack
+ 1);
101 * Machine-dependent startup code for a newly-created thread.
104 _thrp_setup(ulwp_t
*self
)
106 self
->ul_ustack
.ss_sp
= (void *)(self
->ul_stktop
- self
->ul_stksiz
);
107 self
->ul_ustack
.ss_size
= self
->ul_stksiz
;
108 self
->ul_ustack
.ss_flags
= 0;
109 (void) setustack(&self
->ul_ustack
);
114 /* signals have been deferred until now */
117 if (self
->ul_cancel_pending
== 2 && !self
->ul_cancel_disabled
)
118 return (NULL
); /* cancelled by pthread_create() */
119 return (self
->ul_startpc(self
->ul_startarg
));
123 _fpinherit(ulwp_t
*ulwp
)
125 ulwp
->ul_fpuenv
.ftag
= 0xffffffff;
129 getgregs(ulwp_t
*ulwp
, gregset_t rs
)
133 if (getlwpstatus(ulwp
->ul_lwpid
, &status
) == 0) {
134 rs
[REG_RBX
] = status
.pr_reg
[REG_RBX
];
135 rs
[REG_R12
] = status
.pr_reg
[REG_R12
];
136 rs
[REG_R13
] = status
.pr_reg
[REG_R13
];
137 rs
[REG_R14
] = status
.pr_reg
[REG_R14
];
138 rs
[REG_R15
] = status
.pr_reg
[REG_R15
];
139 rs
[REG_RBP
] = status
.pr_reg
[REG_RBP
];
140 rs
[REG_RSP
] = status
.pr_reg
[REG_RSP
];
141 rs
[REG_RIP
] = status
.pr_reg
[REG_RIP
];
155 setgregs(ulwp_t
*ulwp
, gregset_t rs
)
159 if (getlwpstatus(ulwp
->ul_lwpid
, &status
) == 0) {
160 status
.pr_reg
[REG_RBX
] = rs
[REG_RBX
];
161 status
.pr_reg
[REG_R12
] = rs
[REG_R12
];
162 status
.pr_reg
[REG_R13
] = rs
[REG_R13
];
163 status
.pr_reg
[REG_R14
] = rs
[REG_R14
];
164 status
.pr_reg
[REG_R15
] = rs
[REG_R15
];
165 status
.pr_reg
[REG_RBP
] = rs
[REG_RBP
];
166 status
.pr_reg
[REG_RSP
] = rs
[REG_RSP
];
167 status
.pr_reg
[REG_RIP
] = rs
[REG_RIP
];
168 (void) putlwpregs(ulwp
->ul_lwpid
, status
.pr_reg
);
173 __csigsetjmp(sigjmp_buf env
, int savemask
, gregset_t rs
)
175 /* LINTED alignment */
176 ucontext_t
*ucp
= (ucontext_t
*)env
;
177 ulwp_t
*self
= curthread
;
179 ucp
->uc_link
= self
->ul_siglink
;
180 if (self
->ul_ustack
.ss_flags
& SS_ONSTACK
)
181 ucp
->uc_stack
= self
->ul_ustack
;
183 ucp
->uc_stack
.ss_sp
=
184 (void *)(self
->ul_stktop
- self
->ul_stksiz
);
185 ucp
->uc_stack
.ss_size
= self
->ul_stksiz
;
186 ucp
->uc_stack
.ss_flags
= 0;
188 ucp
->uc_flags
= UC_STACK
| UC_CPU
;
190 ucp
->uc_flags
|= UC_SIGMASK
;
191 enter_critical(self
);
192 ucp
->uc_sigmask
= self
->ul_sigmask
;
195 (void) memcpy(ucp
->uc_mcontext
.gregs
, rs
, _NGREG
* sizeof (greg_t
));