LEFT | RIGHT |
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.h" | 6 #include "arch.h" |
7 #include "defs.h" | 7 #include "defs.h" |
8 #include "malloc.h" | 8 #include "malloc.h" |
9 #include "os.h" | 9 #include "os.h" |
10 #include "stack.h" | 10 #include "stack.h" |
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 | 731 |
732 typedef struct CgoThreadStart CgoThreadStart; | 732 typedef struct CgoThreadStart CgoThreadStart; |
733 struct CgoThreadStart | 733 struct CgoThreadStart |
734 { | 734 { |
735 M *m; | 735 M *m; |
736 G *g; | 736 G *g; |
737 void (*fn)(void); | 737 void (*fn)(void); |
738 }; | 738 }; |
739 | 739 |
740 // Kick off new m's as needed (up to mcpumax). | 740 // Kick off new m's as needed (up to mcpumax). |
741 // There are already `other' other cpus that will | |
742 // start looking for goroutines shortly. | |
743 // Sched is locked. | 741 // Sched is locked. |
744 static void | 742 static void |
745 matchmg(void) | 743 matchmg(void) |
746 { | 744 { |
747 G *gp; | 745 G *gp; |
748 M *mp; | 746 M *mp; |
749 | 747 |
750 if(m->mallocing || m->gcing) | 748 if(m->mallocing || m->gcing) |
751 return; | 749 return; |
752 | 750 |
753 while(haveg() && canaddmcpu()) { | 751 while(haveg() && canaddmcpu()) { |
754 gp = gget(); | 752 gp = gget(); |
755 if(gp == nil) | 753 if(gp == nil) |
756 runtime·throw("gget inconsistency"); | 754 runtime·throw("gget inconsistency"); |
757 | 755 |
758 // Find the m that will run gp. | 756 // Find the m that will run gp. |
759 if((mp = mget(gp)) == nil) | 757 if((mp = mget(gp)) == nil) |
760 mp = runtime·newm(); | 758 mp = runtime·newm(); |
761 mnextg(mp, gp); | 759 mnextg(mp, gp); |
762 } | 760 } |
763 } | 761 } |
764 | 762 |
| 763 // Create a new m. It will start off with a call to runtime·mstart. |
765 M* | 764 M* |
766 runtime·newm(void) | 765 runtime·newm(void) |
767 { | 766 { |
768 M *m; | 767 M *m; |
769 | 768 |
770 m = runtime·malloc(sizeof(M)); | 769 m = runtime·malloc(sizeof(M)); |
771 mcommoninit(m); | 770 mcommoninit(m); |
772 | 771 |
773 if(runtime·iscgo) { | 772 if(runtime·iscgo) { |
774 CgoThreadStart ts; | 773 CgoThreadStart ts; |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 | 986 |
988 // Gosched returned, so we're allowed to run now. | 987 // Gosched returned, so we're allowed to run now. |
989 // Delete the gcstack information that we left for | 988 // Delete the gcstack information that we left for |
990 // the garbage collector during the system call. | 989 // the garbage collector during the system call. |
991 // Must wait until now because until gosched returns | 990 // Must wait until now because until gosched returns |
992 // we don't know for sure that the garbage collector | 991 // we don't know for sure that the garbage collector |
993 // is not running. | 992 // is not running. |
994 g->gcstack = nil; | 993 g->gcstack = nil; |
995 } | 994 } |
996 | 995 |
| 996 // Called from runtime·lessstack when returning from a function which |
| 997 // allocated a new stack segment. The function's return value is in |
| 998 // m->cret. |
997 void | 999 void |
998 runtime·oldstack(void) | 1000 runtime·oldstack(void) |
999 { | 1001 { |
1000 Stktop *top, old; | 1002 Stktop *top, old; |
1001 uint32 argsize; | 1003 uint32 argsize; |
1002 byte *sp; | 1004 byte *sp; |
1003 G *g1; | 1005 G *g1; |
1004 int32 goid; | 1006 int32 goid; |
1005 | 1007 |
1006 //printf("oldstack m->cret=%p\n", m->cret); | 1008 //printf("oldstack m->cret=%p\n", m->cret); |
(...skipping 11 matching lines...) Expand all Loading... |
1018 USED(goid); | 1020 USED(goid); |
1019 | 1021 |
1020 if(old.free != 0) | 1022 if(old.free != 0) |
1021 runtime·stackfree(g1->stackguard - StackGuard, old.free); | 1023 runtime·stackfree(g1->stackguard - StackGuard, old.free); |
1022 g1->stackbase = old.stackbase; | 1024 g1->stackbase = old.stackbase; |
1023 g1->stackguard = old.stackguard; | 1025 g1->stackguard = old.stackguard; |
1024 | 1026 |
1025 runtime·gogo(&old.gobuf, m->cret); | 1027 runtime·gogo(&old.gobuf, m->cret); |
1026 } | 1028 } |
1027 | 1029 |
| 1030 // Called from reflect·call or from runtime·morestack when a new |
| 1031 // stack segment is needed. Allocate a new stack big enough for |
| 1032 // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, |
| 1033 // and then act as though runtime·lessstack called the function at |
| 1034 // m->morepc. |
1028 void | 1035 void |
1029 runtime·newstack(void) | 1036 runtime·newstack(void) |
1030 { | 1037 { |
1031 int32 framesize, argsize; | 1038 int32 framesize, argsize; |
1032 Stktop *top; | 1039 Stktop *top; |
1033 byte *stk, *sp; | 1040 byte *stk, *sp; |
1034 G *g1; | 1041 G *g1; |
1035 Gobuf label; | 1042 Gobuf label; |
1036 bool reflectcall; | 1043 bool reflectcall; |
1037 uintptr free; | 1044 uintptr free; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 // Continue as if lessstack had just called m->morepc | 1112 // Continue as if lessstack had just called m->morepc |
1106 // (the PC that decided to grow the stack). | 1113 // (the PC that decided to grow the stack). |
1107 label.sp = sp; | 1114 label.sp = sp; |
1108 label.pc = (byte*)runtime·lessstack; | 1115 label.pc = (byte*)runtime·lessstack; |
1109 label.g = m->curg; | 1116 label.g = m->curg; |
1110 runtime·gogocall(&label, m->morepc); | 1117 runtime·gogocall(&label, m->morepc); |
1111 | 1118 |
1112 *(int32*)345 = 123; // never return | 1119 *(int32*)345 = 123; // never return |
1113 } | 1120 } |
1114 | 1121 |
| 1122 // Hook used by runtime·malg to call runtime·stackalloc on the |
| 1123 // scheduler stack. This exists because runtime·stackalloc insists |
| 1124 // on being called on the scheduler stack, to avoid trying to grow |
| 1125 // the stack while allocating a new stack segment. |
1115 static void | 1126 static void |
1116 mstackalloc(G *gp) | 1127 mstackalloc(G *gp) |
1117 { | 1128 { |
1118 gp->param = runtime·stackalloc((uintptr)gp->param); | 1129 gp->param = runtime·stackalloc((uintptr)gp->param); |
1119 runtime·gogo(&gp->sched, 0); | 1130 runtime·gogo(&gp->sched, 0); |
1120 } | 1131 } |
1121 | 1132 |
| 1133 // Allocate a new g, with a stack big enough for stacksize bytes. |
1122 G* | 1134 G* |
1123 runtime·malg(int32 stacksize) | 1135 runtime·malg(int32 stacksize) |
1124 { | 1136 { |
1125 G *newg; | 1137 G *newg; |
1126 byte *stk; | 1138 byte *stk; |
1127 | 1139 |
1128 newg = runtime·malloc(sizeof(G)); | 1140 newg = runtime·malloc(sizeof(G)); |
1129 if(stacksize >= 0) { | 1141 if(stacksize >= 0) { |
1130 if(g == m->g0) { | 1142 if(g == m->g0) { |
1131 // running on scheduler stack already. | 1143 // running on scheduler stack already. |
1132 stk = runtime·stackalloc(StackSystem + stacksize); | 1144 stk = runtime·stackalloc(StackSystem + stacksize); |
1133 } else { | 1145 } else { |
1134 // have to call stackalloc on scheduler stack. | 1146 // have to call stackalloc on scheduler stack. |
1135 g->param = (void*)(StackSystem + stacksize); | 1147 g->param = (void*)(StackSystem + stacksize); |
1136 runtime·mcall(mstackalloc); | 1148 runtime·mcall(mstackalloc); |
1137 stk = g->param; | 1149 stk = g->param; |
1138 g->param = nil; | 1150 g->param = nil; |
1139 } | 1151 } |
1140 newg->stack0 = stk; | 1152 newg->stack0 = stk; |
1141 newg->stackguard = stk + StackGuard; | 1153 newg->stackguard = stk + StackGuard; |
1142 newg->stackbase = stk + StackSystem + stacksize - sizeof(Stktop)
; | 1154 newg->stackbase = stk + StackSystem + stacksize - sizeof(Stktop)
; |
1143 runtime·memclr(newg->stackbase, sizeof(Stktop)); | 1155 runtime·memclr(newg->stackbase, sizeof(Stktop)); |
1144 } | 1156 } |
1145 return newg; | 1157 return newg; |
1146 } | 1158 } |
1147 | 1159 |
1148 /* | 1160 // Create a new g running fn with siz bytes of arguments. |
1149 * Newproc and deferproc need to be textflag 7 | 1161 // Put it on the queue of g's waiting to run. |
1150 * (no possible stack split when nearing overflow) | 1162 // The compiler turns a go statement into a call to this. |
1151 * because they assume that the arguments to fn | 1163 // Cannot split the stack because it assumes that the arguments |
1152 * are available sequentially beginning at &arg0. | 1164 // are available sequentially after &fn; they would not be |
1153 * If a stack split happened, only the one word | 1165 // copied if a stack split occurred. It's OK for this to call |
1154 * arg0 would be copied. It's okay if any functions | 1166 // functions that split the stack. |
1155 * they call split the stack below the newproc frame. | |
1156 */ | |
1157 #pragma textflag 7 | 1167 #pragma textflag 7 |
1158 void | 1168 void |
1159 runtime·newproc(int32 siz, byte* fn, ...) | 1169 runtime·newproc(int32 siz, byte* fn, ...) |
1160 { | 1170 { |
1161 byte *argp; | 1171 byte *argp; |
1162 | 1172 |
1163 if(thechar == '5') | 1173 if(thechar == '5') |
1164 argp = (byte*)(&fn+2); // skip caller's saved LR | 1174 argp = (byte*)(&fn+2); // skip caller's saved LR |
1165 else | 1175 else |
1166 argp = (byte*)(&fn+1); | 1176 argp = (byte*)(&fn+1); |
1167 runtime·newproc1(fn, argp, siz, 0, runtime·getcallerpc(&siz)); | 1177 runtime·newproc1(fn, argp, siz, 0, runtime·getcallerpc(&siz)); |
1168 } | 1178 } |
1169 | 1179 |
| 1180 // Create a new g running fn with narg bytes of arguments starting |
| 1181 // at argp and returning nret bytes of results. callerpc is the |
| 1182 // address of the go statement that created this. The new g is put |
| 1183 // on the queue of g's waiting to run. |
1170 G* | 1184 G* |
1171 runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc) | 1185 runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc) |
1172 { | 1186 { |
1173 byte *sp; | 1187 byte *sp; |
1174 G *newg; | 1188 G *newg; |
1175 int32 siz; | 1189 int32 siz; |
1176 | 1190 |
1177 //printf("newproc1 %p %p narg=%d nret=%d\n", fn, argp, narg, nret); | 1191 //printf("newproc1 %p %p narg=%d nret=%d\n", fn, argp, narg, nret); |
1178 siz = narg + nret; | 1192 siz = narg + nret; |
1179 siz = (siz+7) & ~7; | 1193 siz = (siz+7) & ~7; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1220 runtime·sched.goidgen++; | 1234 runtime·sched.goidgen++; |
1221 newg->goid = runtime·sched.goidgen; | 1235 newg->goid = runtime·sched.goidgen; |
1222 | 1236 |
1223 newprocreadylocked(newg); | 1237 newprocreadylocked(newg); |
1224 schedunlock(); | 1238 schedunlock(); |
1225 | 1239 |
1226 return newg; | 1240 return newg; |
1227 //printf(" goid=%d\n", newg->goid); | 1241 //printf(" goid=%d\n", newg->goid); |
1228 } | 1242 } |
1229 | 1243 |
| 1244 // Create a new deferred function fn with siz bytes of arguments. |
| 1245 // The compiler turns a defer statement into a call to this. |
| 1246 // Cannot split the stack because it assumes that the arguments |
| 1247 // are available sequentially after &fn; they would not be |
| 1248 // copied if a stack split occurred. It's OK for this to call |
| 1249 // functions that split the stack. |
1230 #pragma textflag 7 | 1250 #pragma textflag 7 |
1231 uintptr | 1251 uintptr |
1232 runtime·deferproc(int32 siz, byte* fn, ...) | 1252 runtime·deferproc(int32 siz, byte* fn, ...) |
1233 { | 1253 { |
1234 Defer *d; | 1254 Defer *d; |
1235 | 1255 |
1236 d = runtime·malloc(sizeof(*d) + siz - sizeof(d->args)); | 1256 d = runtime·malloc(sizeof(*d) + siz - sizeof(d->args)); |
1237 d->fn = fn; | 1257 d->fn = fn; |
1238 d->siz = siz; | 1258 d->siz = siz; |
1239 d->pc = runtime·getcallerpc(&siz); | 1259 d->pc = runtime·getcallerpc(&siz); |
1240 if(thechar == '5') | 1260 if(thechar == '5') |
1241 d->argp = (byte*)(&fn+2); // skip caller's saved link register | 1261 d->argp = (byte*)(&fn+2); // skip caller's saved link register |
1242 else | 1262 else |
1243 d->argp = (byte*)(&fn+1); | 1263 d->argp = (byte*)(&fn+1); |
1244 runtime·memmove(d->args, d->argp, d->siz); | 1264 runtime·memmove(d->args, d->argp, d->siz); |
1245 | 1265 |
1246 d->link = g->defer; | 1266 d->link = g->defer; |
1247 g->defer = d; | 1267 g->defer = d; |
1248 | 1268 |
1249 // deferproc returns 0 normally. | 1269 // deferproc returns 0 normally. |
1250 // a deferred func that stops a panic | 1270 // a deferred func that stops a panic |
1251 // makes the deferproc return 1. | 1271 // makes the deferproc return 1. |
1252 // the code the compiler generates always | 1272 // the code the compiler generates always |
1253 // checks the return value and jumps to the | 1273 // checks the return value and jumps to the |
1254 // end of the function if deferproc returns != 0. | 1274 // end of the function if deferproc returns != 0. |
1255 return 0; | 1275 return 0; |
1256 } | 1276 } |
1257 | 1277 |
| 1278 // Run a deferred function if there is one. |
| 1279 // The compiler inserts a call to this at the end of any |
| 1280 // function which calls defer. |
| 1281 // If there is a deferred function, this will call runtime·jmpdefer, |
| 1282 // which will jump to the deferred function such that it appears |
| 1283 // to have been called by the caller of deferreturn at the point |
| 1284 // just before deferreturn was called. The effect is that deferreturn |
| 1285 // is called again and again until there are no more deferred functions. |
| 1286 // Cannot split the stack because we reuse the caller's frame to |
| 1287 // call the deferred function. |
1258 #pragma textflag 7 | 1288 #pragma textflag 7 |
1259 void | 1289 void |
1260 runtime·deferreturn(uintptr arg0) | 1290 runtime·deferreturn(uintptr arg0) |
1261 { | 1291 { |
1262 Defer *d; | 1292 Defer *d; |
1263 byte *argp, *fn; | 1293 byte *argp, *fn; |
1264 | 1294 |
1265 d = g->defer; | 1295 d = g->defer; |
1266 if(d == nil) | 1296 if(d == nil) |
1267 return; | 1297 return; |
1268 argp = (byte*)&arg0; | 1298 argp = (byte*)&arg0; |
1269 if(d->argp != argp) | 1299 if(d->argp != argp) |
1270 return; | 1300 return; |
1271 runtime·memmove(argp, d->args, d->siz); | 1301 runtime·memmove(argp, d->args, d->siz); |
1272 g->defer = d->link; | 1302 g->defer = d->link; |
1273 fn = d->fn; | 1303 fn = d->fn; |
1274 if(!d->nofree) | 1304 if(!d->nofree) |
1275 runtime·free(d); | 1305 runtime·free(d); |
1276 runtime·jmpdefer(fn, argp); | 1306 runtime·jmpdefer(fn, argp); |
1277 } | 1307 } |
1278 | 1308 |
| 1309 // Run all deferred functions for the current goroutine. |
1279 static void | 1310 static void |
1280 rundefer(void) | 1311 rundefer(void) |
1281 { | 1312 { |
1282 Defer *d; | 1313 Defer *d; |
1283 | 1314 |
1284 while((d = g->defer) != nil) { | 1315 while((d = g->defer) != nil) { |
1285 g->defer = d->link; | 1316 g->defer = d->link; |
1286 reflect·call(d->fn, d->args, d->siz); | 1317 reflect·call(d->fn, d->args, d->siz); |
1287 if(!d->nofree) | 1318 if(!d->nofree) |
1288 runtime·free(d); | 1319 runtime·free(d); |
(...skipping 21 matching lines...) Expand all Loading... |
1310 if(top->free != 0) | 1341 if(top->free != 0) |
1311 runtime·stackfree(stk, top->free); | 1342 runtime·stackfree(stk, top->free); |
1312 } | 1343 } |
1313 | 1344 |
1314 if(sp != nil && (sp < gp->stackguard - StackGuard || gp->stackbase < sp)
) { | 1345 if(sp != nil && (sp < gp->stackguard - StackGuard || gp->stackbase < sp)
) { |
1315 runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackgua
rd - StackGuard, gp->stackbase); | 1346 runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackgua
rd - StackGuard, gp->stackbase); |
1316 runtime·throw("bad unwindstack"); | 1347 runtime·throw("bad unwindstack"); |
1317 } | 1348 } |
1318 } | 1349 } |
1319 | 1350 |
| 1351 // Print all currently active panics. Used when crashing. |
1320 static void | 1352 static void |
1321 printpanics(Panic *p) | 1353 printpanics(Panic *p) |
1322 { | 1354 { |
1323 if(p->link) { | 1355 if(p->link) { |
1324 printpanics(p->link); | 1356 printpanics(p->link); |
1325 runtime·printf("\t"); | 1357 runtime·printf("\t"); |
1326 } | 1358 } |
1327 runtime·printf("panic: "); | 1359 runtime·printf("panic: "); |
1328 runtime·printany(p->arg); | 1360 runtime·printany(p->arg); |
1329 if(p->recovered) | 1361 if(p->recovered) |
1330 runtime·printf(" [recovered]"); | 1362 runtime·printf(" [recovered]"); |
1331 runtime·printf("\n"); | 1363 runtime·printf("\n"); |
1332 } | 1364 } |
1333 | 1365 |
1334 static void recovery(G*); | 1366 static void recovery(G*); |
1335 | 1367 |
| 1368 // The implementation of the predeclared function panic. |
1336 void | 1369 void |
1337 runtime·panic(Eface e) | 1370 runtime·panic(Eface e) |
1338 { | 1371 { |
1339 Defer *d; | 1372 Defer *d; |
1340 Panic *p; | 1373 Panic *p; |
1341 | 1374 |
1342 p = runtime·mal(sizeof *p); | 1375 p = runtime·mal(sizeof *p); |
1343 p->arg = e; | 1376 p->arg = e; |
1344 p->link = g->panic; | 1377 p->link = g->panic; |
1345 p->stackbase = g->stackbase; | 1378 p->stackbase = g->stackbase; |
(...skipping 22 matching lines...) Expand all Loading... |
1368 if(!d->nofree) | 1401 if(!d->nofree) |
1369 runtime·free(d); | 1402 runtime·free(d); |
1370 } | 1403 } |
1371 | 1404 |
1372 // ran out of deferred calls - old-school panic now | 1405 // ran out of deferred calls - old-school panic now |
1373 runtime·startpanic(); | 1406 runtime·startpanic(); |
1374 printpanics(g->panic); | 1407 printpanics(g->panic); |
1375 runtime·dopanic(0); | 1408 runtime·dopanic(0); |
1376 } | 1409 } |
1377 | 1410 |
| 1411 // Unwind the stack after a deferred function calls recover |
| 1412 // after a panic. Then arrange to continue running as though |
| 1413 // the caller of the deferred function returned normally. |
1378 static void | 1414 static void |
1379 recovery(G *gp) | 1415 recovery(G *gp) |
1380 { | 1416 { |
1381 Defer *d; | 1417 Defer *d; |
1382 | 1418 |
1383 // Rewind gp's stack; we're running on m->g0's stack. | 1419 // Rewind gp's stack; we're running on m->g0's stack. |
1384 d = gp->defer; | 1420 d = gp->defer; |
1385 gp->defer = d->link; | 1421 gp->defer = d->link; |
1386 | 1422 |
1387 // Unwind to the stack frame with d's arguments in it. | 1423 // Unwind to the stack frame with d's arguments in it. |
(...skipping 11 matching lines...) Expand all Loading... |
1399 if(thechar == '5') | 1435 if(thechar == '5') |
1400 gp->sched.sp = (byte*)d->argp - 4*sizeof(uintptr); | 1436 gp->sched.sp = (byte*)d->argp - 4*sizeof(uintptr); |
1401 else | 1437 else |
1402 gp->sched.sp = (byte*)d->argp - 2*sizeof(uintptr); | 1438 gp->sched.sp = (byte*)d->argp - 2*sizeof(uintptr); |
1403 gp->sched.pc = d->pc; | 1439 gp->sched.pc = d->pc; |
1404 if(!d->nofree) | 1440 if(!d->nofree) |
1405 runtime·free(d); | 1441 runtime·free(d); |
1406 runtime·gogo(&gp->sched, 1); | 1442 runtime·gogo(&gp->sched, 1); |
1407 } | 1443 } |
1408 | 1444 |
1409 #pragma textflag 7» /* no split, or else g->stackguard is not the stack for
fp */ | 1445 // The implementation of the predeclared function recover. |
| 1446 // Cannot split the stack because it needs to reliably |
| 1447 // find the stack segment of its caller. |
| 1448 #pragma textflag 7 |
1410 void | 1449 void |
1411 runtime·recover(byte *argp, Eface ret) | 1450 runtime·recover(byte *argp, Eface ret) |
1412 { | 1451 { |
1413 Stktop *top, *oldtop; | 1452 Stktop *top, *oldtop; |
1414 Panic *p; | 1453 Panic *p; |
1415 | 1454 |
1416 // Must be a panic going on. | 1455 // Must be a panic going on. |
1417 if((p = g->panic) == nil || p->recovered) | 1456 if((p = g->panic) == nil || p->recovered) |
1418 goto nomatch; | 1457 goto nomatch; |
1419 | 1458 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 rundefer(); | 1550 rundefer(); |
1512 runtime·goexit(); | 1551 runtime·goexit(); |
1513 } | 1552 } |
1514 | 1553 |
1515 void | 1554 void |
1516 runtime·Gosched(void) | 1555 runtime·Gosched(void) |
1517 { | 1556 { |
1518 runtime·gosched(); | 1557 runtime·gosched(); |
1519 } | 1558 } |
1520 | 1559 |
| 1560 // Implementation of runtime.GOMAXPROCS. |
1521 // delete when scheduler is stronger | 1561 // delete when scheduler is stronger |
1522 int32 | 1562 int32 |
1523 runtime·gomaxprocsfunc(int32 n) | 1563 runtime·gomaxprocsfunc(int32 n) |
1524 { | 1564 { |
1525 int32 ret; | 1565 int32 ret; |
1526 uint32 v; | 1566 uint32 v; |
1527 | 1567 |
1528 schedlock(); | 1568 schedlock(); |
1529 ret = runtime·gomaxprocs; | 1569 ret = runtime·gomaxprocs; |
1530 if(n <= 0) | 1570 if(n <= 0) |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1626 runtime·throw("runtime: mcall function returned"); | 1666 runtime·throw("runtime: mcall function returned"); |
1627 } | 1667 } |
1628 | 1668 |
1629 static struct { | 1669 static struct { |
1630 Lock; | 1670 Lock; |
1631 void (*fn)(uintptr*, int32); | 1671 void (*fn)(uintptr*, int32); |
1632 int32 hz; | 1672 int32 hz; |
1633 uintptr pcbuf[100]; | 1673 uintptr pcbuf[100]; |
1634 } prof; | 1674 } prof; |
1635 | 1675 |
| 1676 // Called if we receive a SIGPROF signal. |
1636 void | 1677 void |
1637 runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp) | 1678 runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp) |
1638 { | 1679 { |
1639 int32 n; | 1680 int32 n; |
1640 | 1681 |
1641 if(prof.fn == nil || prof.hz == 0) | 1682 if(prof.fn == nil || prof.hz == 0) |
1642 return; | 1683 return; |
1643 | 1684 |
1644 runtime·lock(&prof); | 1685 runtime·lock(&prof); |
1645 if(prof.fn == nil) { | 1686 if(prof.fn == nil) { |
1646 runtime·unlock(&prof); | 1687 runtime·unlock(&prof); |
1647 return; | 1688 return; |
1648 } | 1689 } |
1649 n = runtime·gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf
)); | 1690 n = runtime·gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf
)); |
1650 if(n > 0) | 1691 if(n > 0) |
1651 prof.fn(prof.pcbuf, n); | 1692 prof.fn(prof.pcbuf, n); |
1652 runtime·unlock(&prof); | 1693 runtime·unlock(&prof); |
1653 } | 1694 } |
1654 | 1695 |
| 1696 // Arrange to call fn with a traceback hz times a second. |
1655 void | 1697 void |
1656 runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz) | 1698 runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz) |
1657 { | 1699 { |
1658 // Force sane arguments. | 1700 // Force sane arguments. |
1659 if(hz < 0) | 1701 if(hz < 0) |
1660 hz = 0; | 1702 hz = 0; |
1661 if(hz == 0) | 1703 if(hz == 0) |
1662 fn = nil; | 1704 fn = nil; |
1663 if(fn == nil) | 1705 if(fn == nil) |
1664 hz = 0; | 1706 hz = 0; |
(...skipping 10 matching lines...) Expand all Loading... |
1675 runtime·lock(&runtime·sched); | 1717 runtime·lock(&runtime·sched); |
1676 runtime·sched.profilehz = hz; | 1718 runtime·sched.profilehz = hz; |
1677 runtime·unlock(&runtime·sched); | 1719 runtime·unlock(&runtime·sched); |
1678 | 1720 |
1679 if(hz != 0) | 1721 if(hz != 0) |
1680 runtime·resetcpuprofiler(hz); | 1722 runtime·resetcpuprofiler(hz); |
1681 } | 1723 } |
1682 | 1724 |
1683 void (*libcgo_setenv)(byte**); | 1725 void (*libcgo_setenv)(byte**); |
1684 | 1726 |
| 1727 // Update the C environment if cgo is loaded. |
| 1728 // Called from os.Setenv. |
1685 void | 1729 void |
1686 os·setenv_c(String k, String v) | 1730 os·setenv_c(String k, String v) |
1687 { | 1731 { |
1688 byte *arg[2]; | 1732 byte *arg[2]; |
1689 | 1733 |
1690 if(libcgo_setenv == nil) | 1734 if(libcgo_setenv == nil) |
1691 return; | 1735 return; |
1692 | 1736 |
1693 arg[0] = runtime·malloc(k.len + 1); | 1737 arg[0] = runtime·malloc(k.len + 1); |
1694 runtime·memmove(arg[0], k.str, k.len); | 1738 runtime·memmove(arg[0], k.str, k.len); |
1695 arg[0][k.len] = 0; | 1739 arg[0][k.len] = 0; |
1696 | 1740 |
1697 arg[1] = runtime·malloc(v.len + 1); | 1741 arg[1] = runtime·malloc(v.len + 1); |
1698 runtime·memmove(arg[1], v.str, v.len); | 1742 runtime·memmove(arg[1], v.str, v.len); |
1699 arg[1][v.len] = 0; | 1743 arg[1][v.len] = 0; |
1700 | 1744 |
1701 runtime·asmcgocall((void*)libcgo_setenv, arg); | 1745 runtime·asmcgocall((void*)libcgo_setenv, arg); |
1702 runtime·free(arg[0]); | 1746 runtime·free(arg[0]); |
1703 runtime·free(arg[1]); | 1747 runtime·free(arg[1]); |
1704 } | 1748 } |
LEFT | RIGHT |