for(i=0; i<libraryp; i++) {
if(debug['v'])
Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i].file, library[i].objref);
+ iscgo |= strcmp(library[i].pkg, "runtime/cgo") == 0;
objfile(library[i].file, library[i].pkg);
}
EXTERN char* thestring;
EXTERN int ndynexp;
EXTERN int havedynamic;
+EXTERN int iscgo;
EXTERN Segment segtext;
EXTERN Segment segdata;
// Commit size must be strictly less than reserve
// size otherwise reserve will be rounded up to a
// larger size, as verified with VMMap.
- set(SizeOfStackReserve, 0x00010000);
- set(SizeOfStackCommit, 0x0000ffff);
+
+ // Go code would be OK with 64k stacks, but we need larger stacks for cgo.
+ // That default stack reserve size affects only the main thread,
+ // for other threads we specify stack size in runtime explicitly
+ // (runtime knows whether cgo is enabled or not).
+ // If you change stack reserve sizes here,
+ // change them in runtime/cgo/windows_386/amd64.c as well.
+ if(!iscgo) {
+ set(SizeOfStackReserve, 0x00010000);
+ set(SizeOfStackCommit, 0x0000ffff);
+ } else {
+ set(SizeOfStackReserve, pe64 ? 0x00200000 : 0x00100000);
+ // account for 2 guard pages
+ set(SizeOfStackCommit, (pe64 ? 0x00200000 : 0x00100000) - 0x2000);
+ }
set(SizeOfHeapReserve, 0x00100000);
set(SizeOfHeapCommit, 0x00001000);
set(NumberOfRvaAndSizes, 16);
MOVL AX, 120(SP) // save argc, argv away
MOVL BX, 124(SP)
+ // set default stack bounds.
+ // initcgo may update stackguard.
+ MOVL $runtime·g0(SB), BP
+ LEAL (-64*1024+104)(SP), BX
+ MOVL BX, g_stackguard(BP)
+ MOVL SP, g_stackbase(BP)
+
// if there is an initcgo, call it to let it
// initialize and to set up GS. if not,
// we set up GS ourselves.
MOVL initcgo(SB), AX
TESTL AX, AX
JZ needtls
- PUSHL $runtime·g0(SB)
+ PUSHL BP
CALL AX
- POPL AX
+ POPL BP
// skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
CMPL runtime·iswindows(SB), $0
JEQ ok
// save m->g0 = g0
MOVL CX, m_g0(AX)
- // create istack out of the OS stack
- // if there is an initcgo, it had setup stackguard for us
- MOVL initcgo(SB), AX
- TESTL AX, AX
- JNZ stackok
- LEAL (-64*1024+104)(SP), AX // TODO: 104?
- MOVL AX, g_stackguard(CX)
-stackok:
- MOVL SP, g_stackbase(CX)
-
CALL runtime·emptyfunc(SB) // fault if stack check is wrong
// convention is D is always cleared
ANDQ $~15, SP
MOVQ AX, 16(SP)
MOVQ BX, 24(SP)
+
+ // create istack out of the given (operating system) stack.
+ // initcgo may update stackguard.
+ MOVQ $runtime·g0(SB), DI
+ LEAQ (-8192+104)(SP), BX
+ MOVQ BX, g_stackguard(DI)
+ MOVQ SP, g_stackbase(DI)
// if there is an initcgo, call it.
MOVQ initcgo(SB), AX
TESTQ AX, AX
JZ needtls
- LEAQ runtime·g0(SB), DI
- CALL AX
+ CALL AX // g0 already in DI
CMPL runtime·iswindows(SB), $0
JEQ ok
// save m->g0 = g0
MOVQ CX, m_g0(AX)
- // create istack out of the given (operating system) stack
- // if there is an initcgo, it had setup stackguard for us
- MOVQ initcgo(SB), AX
- TESTQ AX, AX
- JNZ stackok
- LEAQ (-8192+104)(SP), AX
- MOVQ AX, g_stackguard(CX)
-stackok:
- MOVQ SP, g_stackbase(CX)
-
CLD // convention is D is always left cleared
CALL runtime·check(SB)
static void *threadentry(void*);
-/* From what I've read 1MB is default for 32-bit Linux.
- Allocation granularity on Windows is typically 64 KB. */
+/* 1MB is default stack size for 32-bit Windows.
+ Allocation granularity on Windows is typically 64 KB.
+ The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */
#define STACKSIZE (1*1024*1024)
static void
xinitcgo(G *g)
{
int tmp;
- g->stackguard = (uintptr)&tmp - STACKSIZE + 4096;
+ g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
}
void (*initcgo)(G*) = xinitcgo;
void
libcgo_sys_thread_start(ThreadStart *ts)
{
- ts->g->stackguard = STACKSIZE;
- _beginthread(threadentry, STACKSIZE, ts);
+ _beginthread(threadentry, 0, ts);
}
static void*
free(v);
ts.g->stackbase = (uintptr)&ts;
-
- /*
- * libcgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+ ts.g->stackguard = (uintptr)&ts - STACKSIZE + 8*1024;
/*
* Set specific keys in thread local storage.
static void *threadentry(void*);
-/* From what I've read 2MB is default for 64-bit Linux.
- Allocation granularity on Windows is typically 64 KB. */
+/* 2MB is default stack size for 64-bit Windows.
+ Allocation granularity on Windows is typically 64 KB.
+ The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */
#define STACKSIZE (2*1024*1024)
static void
xinitcgo(G *g)
{
int tmp;
- g->stackguard = (uintptr)&tmp - STACKSIZE + 4096;
+ g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
}
void (*initcgo)(G*) = xinitcgo;
void
libcgo_sys_thread_start(ThreadStart *ts)
{
- ts->g->stackguard = STACKSIZE;
- _beginthread(threadentry, STACKSIZE, ts);
+ _beginthread(threadentry, 0, ts);
}
static void*
free(v);
ts.g->stackbase = (uintptr)&ts;
-
- /*
- * libcgo_sys_thread_start set stackguard to stack size;
- * change to actual guard pointer.
- */
- ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+ ts.g->stackguard = (uintptr)&ts - STACKSIZE + 8*1024;
/*
* Set specific keys in thread local storage.
return (uintptr)runtime·stdcall(runtime·CreateEvent, 4, (uintptr)0, (uintptr)0, (uintptr)0, (uintptr)0);
}
+#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
+
void
runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
{
USED(fn); // assuming fn = mstart
thandle = runtime·stdcall(runtime·CreateThread, 6,
- nil, nil, runtime·tstart_stdcall, m, nil, nil);
+ nil, (uintptr)0x20000, runtime·tstart_stdcall, m,
+ STACK_SIZE_PARAM_IS_A_RESERVATION, nil);
if(thandle == nil) {
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror());
runtime·throw("runtime.newosproc");