blob: ecd4cedab047e7bb2fc4fe138881847170f09fba [file] [log] [blame]
Ken Thompsonaf58f172008-07-14 14:34:27 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#include "runtime.h"
6
7static int32 debug = 0;
8
9void
10sys·goexit(void)
11{
12//prints("goexit goid=");
13//sys·printint(g->goid);
14//prints("\n");
15 g->status = Gdead;
16 sys·gosched();
17}
18
19void
20sys·newproc(int32 siz, byte* fn, byte* arg0)
21{
22 byte *stk, *sp;
23 G *newg;
24
25//prints("newproc siz=");
26//sys·printint(siz);
27//prints(" fn=");
28//sys·printpointer(fn);
29
30 siz = (siz+7) & ~7;
Ken Thompson9e2d1852008-07-17 15:03:39 -070031 if(siz > 1024)
32 throw("sys·newproc: too many args");
Ken Thompsonaf58f172008-07-14 14:34:27 -070033
Ken Thompsone7d549f2008-07-16 13:50:23 -070034 // try to rip off an old goroutine
35 for(newg=allg; newg!=nil; newg=newg->alllink)
36 if(newg->status == Gdead)
37 break;
38
39 if(newg == nil) {
40 newg = mal(sizeof(G));
41 stk = mal(4096);
42 newg->stack0 = stk;
43
44 newg->status = Gwaiting;
45 newg->alllink = allg;
46 allg = newg;
47 } else {
48 stk = newg->stack0;
49 newg->status = Gwaiting;
50 }
51
Ken Thompsonaf58f172008-07-14 14:34:27 -070052 newg->stackguard = stk+160;
53
54 sp = stk + 4096 - 4*8;
55 newg->stackbase = sp;
56
57 sp -= siz;
58 mcpy(sp, (byte*)&arg0, siz);
59
60 sp -= 8;
61 *(byte**)sp = (byte*)sys·goexit;
62
63 sp -= 8; // retpc used by gogo
64 newg->sched.SP = sp;
65 newg->sched.PC = fn;
66
67 goidgen++;
68 newg->goid = goidgen;
69
70 newg->status = Grunnable;
Ken Thompsonaf58f172008-07-14 14:34:27 -070071
72//prints(" goid=");
73//sys·printint(newg->goid);
74//prints("\n");
75}
76
77G*
78select(void)
79{
Ken Thompsone7d549f2008-07-16 13:50:23 -070080 G *gp;
Ken Thompsonaf58f172008-07-14 14:34:27 -070081
Ken Thompsone7d549f2008-07-16 13:50:23 -070082 gp = m->lastg;
83 if(gp == nil)
84 gp = allg;
85
86 for(gp=gp->alllink; gp!=nil; gp=gp->alllink) {
87 if(gp->status == Grunnable) {
88 m->lastg = gp;
89 return gp;
90 }
Ken Thompsonaf58f172008-07-14 14:34:27 -070091 }
Ken Thompsone7d549f2008-07-16 13:50:23 -070092 for(gp=allg; gp!=nil; gp=gp->alllink) {
93 if(gp->status == Grunnable) {
94 m->lastg = gp;
95 return gp;
96 }
97 }
98 return nil;
Ken Thompsonaf58f172008-07-14 14:34:27 -070099}
100
101void
102gom0init(void)
103{
104 gosave(&m->sched);
105 sys·gosched();
106}
107
108void
109sys·gosched(void)
110{
111 G* gp;
112
113 if(g != m->g0) {
114 if(gosave(&g->sched))
115 return;
116 g = m->g0;
117 gogo(&m->sched);
118 }
119 gp = select();
120 if(gp == nil) {
121// prints("sched: no more work\n");
122 sys·exit(0);
123 }
124
125 m->curg = gp;
126 g = gp;
127 gogo(&gp->sched);
128}
129
130//
131// the calling sequence for a routine that
132// needs N bytes stack, A args.
133//
134// N1 = (N+160 > 4096)? N+160: 0
135// A1 = A
136//
137// if N <= 75
138// CMPQ SP, 0(R15)
139// JHI 4(PC)
140// MOVQ $(N1<<0) | (A1<<32)), AX
141// MOVQ AX, 0(R14)
142// CALL sys·morestack(SB)
143//
144// if N > 75
145// LEAQ (-N-75)(SP), AX
146// CMPQ AX, 0(R15)
147// JHI 4(PC)
148// MOVQ $(N1<<0) | (A1<<32)), AX
149// MOVQ AX, 0(R14)
150// CALL sys·morestack(SB)
151//
152
153void
154oldstack(void)
155{
156 Stktop *top;
157 uint32 siz2;
158 byte *sp;
159
160// prints("oldstack m->cret = ");
161// sys·printpointer((void*)m->cret);
162// prints("\n");
163
164 top = (Stktop*)m->curg->stackbase;
165
166 m->curg->stackbase = top->oldbase;
167 m->curg->stackguard = top->oldguard;
168 siz2 = (top->magic>>32) & 0xffffLL;
169
170 sp = (byte*)top;
171 if(siz2 > 0) {
172 siz2 = (siz2+7) & ~7;
173 sp -= siz2;
174 mcpy(top->oldsp+16, sp, siz2);
175 }
176
177 m->morestack.SP = top->oldsp+8;
178 m->morestack.PC = (byte*)(*(uint64*)(top->oldsp+8));
179
180// prints("oldstack sp=");
181// sys·printpointer(m->morestack.SP);
182// prints(" pc=");
183// sys·printpointer(m->morestack.PC);
184// prints("\n");
185
186 gogoret(&m->morestack, m->cret);
187}
188
189void
190newstack(void)
191{
192 int32 siz1, siz2;
193 Stktop *top;
194 byte *stk, *sp;
195 void (*fn)(void);
196
197 siz1 = m->morearg & 0xffffffffLL;
198 siz2 = (m->morearg>>32) & 0xffffLL;
199
200// prints("newstack siz1=");
201// sys·printint(siz1);
202// prints(" siz2=");
203// sys·printint(siz2);
204// prints(" moresp=");
205// sys·printpointer(m->moresp);
206// prints("\n");
207
208 if(siz1 < 4096)
209 siz1 = 4096;
210 stk = mal(siz1 + 1024);
211 stk += 512;
212
213 top = (Stktop*)(stk+siz1-sizeof(*top));
214
215 top->oldbase = m->curg->stackbase;
216 top->oldguard = m->curg->stackguard;
217 top->oldsp = m->moresp;
218 top->magic = m->morearg;
219
220 m->curg->stackbase = (byte*)top;
221 m->curg->stackguard = stk + 160;
222
223 sp = (byte*)top;
224
225 if(siz2 > 0) {
226 siz2 = (siz2+7) & ~7;
227 sp -= siz2;
228 mcpy(sp, m->moresp+16, siz2);
229 }
230
231 g = m->curg;
232 fn = (void(*)(void))(*(uint64*)m->moresp);
233
234// prints("fn=");
235// sys·printpointer(fn);
236// prints("\n");
237
238 setspgoto(sp, fn, retfromnewstack);
239
240 *(int32*)345 = 123; // never return
241}
242
243void
244sys·morestack(uint64 u)
245{
246 while(g == m->g0) {
247 // very bad news
248 *(int32*)123 = 123;
249 }
250
251 g = m->g0;
252 m->moresp = (byte*)(&u-1);
253 setspgoto(m->sched.SP, newstack, nil);
254
255 *(int32*)234 = 123; // never return
256}