LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "arch_GOARCH.h" | 6 #include "arch_GOARCH.h" |
7 #include "malloc.h" | 7 #include "malloc.h" |
8 #include "stack.h" | 8 #include "stack.h" |
9 | 9 |
10 enum | 10 enum |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 gp->stackguard = top->stackguard; | 176 gp->stackguard = top->stackguard; |
177 gp->stackguard0 = gp->stackguard; | 177 gp->stackguard0 = gp->stackguard; |
178 | 178 |
179 if(top->free != 0) | 179 if(top->free != 0) |
180 runtime·stackfree(old, top->free); | 180 runtime·stackfree(old, top->free); |
181 | 181 |
182 gp->status = oldstatus; | 182 gp->status = oldstatus; |
183 runtime·gogo(&gp->sched); | 183 runtime·gogo(&gp->sched); |
184 } | 184 } |
185 | 185 |
186 // Called from reflect·call or from runtime·morestack when a new | 186 // Called from runtime·newstackcall or from runtime·morestack when a new |
187 // stack segment is needed. Allocate a new stack big enough for | 187 // stack segment is needed. Allocate a new stack big enough for |
188 // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, | 188 // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, |
189 // and then act as though runtime·lessstack called the function at | 189 // and then act as though runtime·lessstack called the function at |
190 // m->morepc. | 190 // m->morepc. |
191 void | 191 void |
192 runtime·newstack(void) | 192 runtime·newstack(void) |
193 { | 193 { |
194 int32 framesize, argsize, oldstatus; | 194 int32 framesize, argsize, oldstatus; |
195 Stktop *top; | 195 Stktop *top; |
196 byte *stk; | 196 byte *stk; |
197 uintptr sp; | 197 uintptr sp; |
198 uintptr *src, *dst, *dstend; | 198 uintptr *src, *dst, *dstend; |
199 G *gp; | 199 G *gp; |
200 Gobuf label; | 200 Gobuf label; |
201 » bool reflectcall; | 201 » bool newstackcall; |
202 uintptr free; | 202 uintptr free; |
203 | 203 |
204 if(m->morebuf.g != m->curg) { | 204 if(m->morebuf.g != m->curg) { |
205 runtime·printf("runtime: newstack called from g=%p\n" | 205 runtime·printf("runtime: newstack called from g=%p\n" |
206 "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n", | 206 "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n", |
207 m->morebuf.g, m, m->curg, m->g0, m->gsignal); | 207 m->morebuf.g, m, m->curg, m->g0, m->gsignal); |
208 runtime·throw("runtime: wrong goroutine in newstack"); | 208 runtime·throw("runtime: wrong goroutine in newstack"); |
209 } | 209 } |
210 | 210 |
211 // gp->status is usually Grunning, but it could be Gsyscall if a stack s
plit | 211 // gp->status is usually Grunning, but it could be Gsyscall if a stack s
plit |
212 // happens during a function call inside entersyscall. | 212 // happens during a function call inside entersyscall. |
213 gp = m->curg; | 213 gp = m->curg; |
214 oldstatus = gp->status; | 214 oldstatus = gp->status; |
215 | 215 |
216 framesize = m->moreframesize; | 216 framesize = m->moreframesize; |
217 argsize = m->moreargsize; | 217 argsize = m->moreargsize; |
218 gp->status = Gwaiting; | 218 gp->status = Gwaiting; |
219 gp->waitreason = "stack split"; | 219 gp->waitreason = "stack split"; |
220 » reflectcall = framesize==1; | 220 » newstackcall = framesize==1; |
221 » if(reflectcall) | 221 » if(newstackcall) |
222 framesize = 0; | 222 framesize = 0; |
223 | 223 |
224 » // For reflectcall the context already points to beginning of reflect·ca
ll. | 224 » // For newstackcall the context already points to beginning of runtime·n
ewstackcall. |
225 » if(!reflectcall) | 225 » if(!newstackcall) |
226 runtime·rewindmorestack(&gp->sched); | 226 runtime·rewindmorestack(&gp->sched); |
227 | 227 |
228 sp = gp->sched.sp; | 228 sp = gp->sched.sp; |
229 if(thechar == '6' || thechar == '8') { | 229 if(thechar == '6' || thechar == '8') { |
230 // The call to morestack cost a word. | 230 // The call to morestack cost a word. |
231 sp -= sizeof(uintptr); | 231 sp -= sizeof(uintptr); |
232 } | 232 } |
233 if(StackDebug || sp < gp->stackguard - StackGuard) { | 233 if(StackDebug || sp < gp->stackguard - StackGuard) { |
234 runtime·printf("runtime: newstack framesize=%p argsize=%p sp=%p
stack=[%p, %p]\n" | 234 runtime·printf("runtime: newstack framesize=%p argsize=%p sp=%p
stack=[%p, %p]\n" |
235 "\tmorebuf={pc:%p sp:%p lr:%p}\n" | 235 "\tmorebuf={pc:%p sp:%p lr:%p}\n" |
(...skipping 26 matching lines...) Expand all Loading... |
262 // gp->preempt is set, so it will be preempted next time
. | 262 // gp->preempt is set, so it will be preempted next time
. |
263 gp->stackguard0 = gp->stackguard; | 263 gp->stackguard0 = gp->stackguard; |
264 gp->status = oldstatus; | 264 gp->status = oldstatus; |
265 runtime·gogo(&gp->sched); // never return | 265 runtime·gogo(&gp->sched); // never return |
266 } | 266 } |
267 // Act like goroutine called runtime.Gosched. | 267 // Act like goroutine called runtime.Gosched. |
268 gp->status = oldstatus; | 268 gp->status = oldstatus; |
269 runtime·gosched0(gp); // never return | 269 runtime·gosched0(gp); // never return |
270 } | 270 } |
271 | 271 |
272 » if(reflectcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->st
ackguard) { | 272 » if(newstackcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->s
tackguard) { |
273 » » // special case: called from reflect.call (framesize==1) | 273 » » // special case: called from runtime.newstackcall (framesize==1) |
274 // to call code with an arbitrary argument size, | 274 // to call code with an arbitrary argument size, |
275 // and we have enough space on the current stack. | 275 // and we have enough space on the current stack. |
276 // the new Stktop* is necessary to unwind, but | 276 // the new Stktop* is necessary to unwind, but |
277 // we don't need to create a new segment. | 277 // we don't need to create a new segment. |
278 top = (Stktop*)(m->morebuf.sp - sizeof(*top)); | 278 top = (Stktop*)(m->morebuf.sp - sizeof(*top)); |
279 stk = (byte*)gp->stackguard - StackGuard; | 279 stk = (byte*)gp->stackguard - StackGuard; |
280 free = 0; | 280 free = 0; |
281 } else { | 281 } else { |
282 // allocate new segment. | 282 // allocate new segment. |
283 framesize += argsize; | 283 framesize += argsize; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 sp -= sizeof(void*); | 327 sp -= sizeof(void*); |
328 *(void**)sp = nil; | 328 *(void**)sp = nil; |
329 } | 329 } |
330 | 330 |
331 // Continue as if lessstack had just called m->morepc | 331 // Continue as if lessstack had just called m->morepc |
332 // (the PC that decided to grow the stack). | 332 // (the PC that decided to grow the stack). |
333 runtime·memclr((byte*)&label, sizeof label); | 333 runtime·memclr((byte*)&label, sizeof label); |
334 label.sp = sp; | 334 label.sp = sp; |
335 label.pc = (uintptr)runtime·lessstack; | 335 label.pc = (uintptr)runtime·lessstack; |
336 label.g = m->curg; | 336 label.g = m->curg; |
337 » if(reflectcall) | 337 » if(newstackcall) |
338 runtime·gostartcallfn(&label, (FuncVal*)m->cret); | 338 runtime·gostartcallfn(&label, (FuncVal*)m->cret); |
339 else { | 339 else { |
340 runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sch
ed.ctxt); | 340 runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sch
ed.ctxt); |
341 gp->sched.ctxt = nil; | 341 gp->sched.ctxt = nil; |
342 } | 342 } |
343 gp->status = oldstatus; | 343 gp->status = oldstatus; |
344 runtime·gogo(&label); | 344 runtime·gogo(&label); |
345 | 345 |
346 *(int32*)345 = 123; // never return | 346 *(int32*)345 = 123; // never return |
347 } | 347 } |
348 | 348 |
349 // adjust Gobuf as if it executed a call to fn | 349 // adjust Gobuf as if it executed a call to fn |
350 // and then did an immediate gosave. | 350 // and then did an immediate gosave. |
351 void | 351 void |
352 runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv) | 352 runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv) |
353 { | 353 { |
354 runtime·gostartcall(gobuf, fv->fn, fv); | 354 runtime·gostartcall(gobuf, fv->fn, fv); |
355 } | 355 } |
LEFT | RIGHT |