OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 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 #include "race.h" | 9 #include "race.h" |
10 #include "type.h" | 10 #include "type.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 typedef struct Sched Sched; | 25 typedef struct Sched Sched; |
26 struct Sched { | 26 struct Sched { |
27 Lock; | 27 Lock; |
28 | 28 |
29 uint64 goidgen; | 29 uint64 goidgen; |
30 | 30 |
31 M* midle; // idle m's waiting for work | 31 M* midle; // idle m's waiting for work |
32 int32 nmidle; // number of idle m's waiting for work | 32 int32 nmidle; // number of idle m's waiting for work |
33 int32 nmidlelocked; // number of locked m's waiting for work | 33 int32 nmidlelocked; // number of locked m's waiting for work |
34 int32 mcount; // number of m's that have been created | 34 int32 mcount; // number of m's that have been created |
| 35 int32 maxmcount; // maximum number of m's allowed (or die) |
35 | 36 |
36 P* pidle; // idle P's | 37 P* pidle; // idle P's |
37 uint32 npidle; | 38 uint32 npidle; |
38 uint32 nmspinning; | 39 uint32 nmspinning; |
39 | 40 |
40 // Global runnable queue. | 41 // Global runnable queue. |
41 G* runqhead; | 42 G* runqhead; |
42 G* runqtail; | 43 G* runqtail; |
43 int32 runqsize; | 44 int32 runqsize; |
44 | 45 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 // make & queue new G | 120 // make & queue new G |
120 // call runtime·mstart | 121 // call runtime·mstart |
121 // | 122 // |
122 // The new G calls runtime·main. | 123 // The new G calls runtime·main. |
123 void | 124 void |
124 runtime·schedinit(void) | 125 runtime·schedinit(void) |
125 { | 126 { |
126 int32 n, procs; | 127 int32 n, procs; |
127 byte *p; | 128 byte *p; |
128 | 129 |
| 130 runtime·sched.maxmcount = 10000; |
| 131 |
129 m->nomemprof++; | 132 m->nomemprof++; |
130 runtime·mprofinit(); | 133 runtime·mprofinit(); |
131 runtime·mallocinit(); | 134 runtime·mallocinit(); |
132 mcommoninit(m); | 135 mcommoninit(m); |
133 | 136 |
134 runtime·goargs(); | 137 runtime·goargs(); |
135 runtime·goenvs(); | 138 runtime·goenvs(); |
136 runtime·parsedebugvars(); | 139 runtime·parsedebugvars(); |
137 | 140 |
138 // Allocate internal symbol table representation now, we need it for GC
anyway. | 141 // Allocate internal symbol table representation now, we need it for GC
anyway. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 runtime·goroutineheader(gp); | 280 runtime·goroutineheader(gp); |
278 if(gp->status == Grunning) { | 281 if(gp->status == Grunning) { |
279 runtime·printf("\tgoroutine running on other thread; sta
ck unavailable\n"); | 282 runtime·printf("\tgoroutine running on other thread; sta
ck unavailable\n"); |
280 runtime·printcreatedby(gp); | 283 runtime·printcreatedby(gp); |
281 } else | 284 } else |
282 runtime·traceback(gp->sched.pc, gp->sched.sp, gp->sched.
lr, gp); | 285 runtime·traceback(gp->sched.pc, gp->sched.sp, gp->sched.
lr, gp); |
283 } | 286 } |
284 } | 287 } |
285 | 288 |
286 static void | 289 static void |
| 290 checkmcount(void) |
| 291 { |
| 292 // sched lock is held |
| 293 if(runtime·sched.mcount > runtime·sched.maxmcount) { |
| 294 runtime·printf("runtime: program exceeds %d-thread limit\n", run
time·sched.maxmcount); |
| 295 runtime·throw("thread exhaustion"); |
| 296 } |
| 297 } |
| 298 |
| 299 static void |
287 mcommoninit(M *mp) | 300 mcommoninit(M *mp) |
288 { | 301 { |
289 // If there is no mcache runtime·callers() will crash, | 302 // If there is no mcache runtime·callers() will crash, |
290 // and we are most likely in sysmon thread so the stack is senseless any
way. | 303 // and we are most likely in sysmon thread so the stack is senseless any
way. |
291 if(m->mcache) | 304 if(m->mcache) |
292 runtime·callers(1, mp->createstack, nelem(mp->createstack)); | 305 runtime·callers(1, mp->createstack, nelem(mp->createstack)); |
293 | 306 |
294 mp->fastrand = 0x49f6428aUL + mp->id + runtime·cputicks(); | 307 mp->fastrand = 0x49f6428aUL + mp->id + runtime·cputicks(); |
295 | 308 |
296 runtime·lock(&runtime·sched); | 309 runtime·lock(&runtime·sched); |
297 mp->id = runtime·sched.mcount++; | 310 mp->id = runtime·sched.mcount++; |
298 | 311 » checkmcount(); |
299 runtime·mpreinit(mp); | 312 runtime·mpreinit(mp); |
300 | 313 |
301 // Add to runtime·allm so garbage collector doesn't free m | 314 // Add to runtime·allm so garbage collector doesn't free m |
302 // when it is just in a register or thread-local storage. | 315 // when it is just in a register or thread-local storage. |
303 mp->alllink = runtime·allm; | 316 mp->alllink = runtime·allm; |
304 // runtime·NumCgoCall() iterates over allm w/o schedlock, | 317 // runtime·NumCgoCall() iterates over allm w/o schedlock, |
305 // so we need to publish it safely. | 318 // so we need to publish it safely. |
306 runtime·atomicstorep(&runtime·allm, mp); | 319 runtime·atomicstorep(&runtime·allm, mp); |
307 runtime·unlock(&runtime·sched); | 320 runtime·unlock(&runtime·sched); |
308 } | 321 } |
(...skipping 2505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2814 bool | 2827 bool |
2815 runtime·topofstack(Func *f) | 2828 runtime·topofstack(Func *f) |
2816 { | 2829 { |
2817 return f->entry == (uintptr)runtime·goexit || | 2830 return f->entry == (uintptr)runtime·goexit || |
2818 f->entry == (uintptr)runtime·mstart || | 2831 f->entry == (uintptr)runtime·mstart || |
2819 f->entry == (uintptr)runtime·mcall || | 2832 f->entry == (uintptr)runtime·mcall || |
2820 f->entry == (uintptr)runtime·morestack || | 2833 f->entry == (uintptr)runtime·morestack || |
2821 f->entry == (uintptr)runtime·lessstack || | 2834 f->entry == (uintptr)runtime·lessstack || |
2822 f->entry == (uintptr)_rt0_go; | 2835 f->entry == (uintptr)_rt0_go; |
2823 } | 2836 } |
| 2837 |
| 2838 void |
| 2839 runtime∕debug·setMaxThreads(intgo in, intgo out) |
| 2840 { |
| 2841 runtime·lock(&runtime·sched); |
| 2842 out = runtime·sched.maxmcount; |
| 2843 runtime·sched.maxmcount = in; |
| 2844 checkmcount(); |
| 2845 runtime·unlock(&runtime·sched); |
| 2846 FLUSH(&out); |
| 2847 } |
OLD | NEW |