MOVL $1, AX
RET
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime·casp(SB), 7, $0
+ MOVQ 8(SP), BX
+ MOVQ 16(SP), AX
+ MOVQ 24(SP), CX
+ LOCK
+ CMPXCHGQ CX, 0(BX)
+ JZ 3(PC)
+ MOVL $0, AX
+ RET
+ MOVL $1, AX
+ RET
+
+
// void jmpdefer(fn, sp);
// called from deferreturn.
// 1. pop the caller
#include "runtime.h"
#include "malloc.h"
-// TODO(rsc): Why not just use mheap.Lock?
+// Lock to protect finalizer data structures.
+// Cannot reuse mheap.Lock because the finalizer
+// maintenance requires allocation.
static Lock finlock;
// Finalizer hash table. Direct hash, linear scan, at most 3/4 full.
int32 mcount; // number of ms that have been created
int32 mcpu; // number of ms executing on cpu
int32 mcpumax; // max number of ms allowed on cpu
- int32 gomaxprocs;
int32 msyscall; // number of ms in system calls
int32 predawn; // running initialization, don't run new gs.
};
Sched runtime·sched;
+int32 gomaxprocs;
// Scheduling helpers. Sched must be locked.
static void gput(G*); // put/get on ghead/gtail
// For debugging:
// Allocate internal symbol table representation now,
// so that we don't need to call malloc when we crash.
- // findfunc(0);
+ // runtime·findfunc(0);
- runtime·sched.gomaxprocs = 1;
+ runtime·gomaxprocs = 1;
p = runtime·getenv("GOMAXPROCS");
if(p != nil && (n = runtime·atoi(p)) != 0)
- runtime·sched.gomaxprocs = n;
- runtime·sched.mcpumax = runtime·sched.gomaxprocs;
+ runtime·gomaxprocs = n;
+ runtime·sched.mcpumax = runtime·gomaxprocs;
runtime·sched.mcount = 1;
runtime·sched.predawn = 1;
{
runtime·lock(&runtime·sched);
runtime·gcwaiting = 0;
- runtime·sched.mcpumax = runtime·sched.gomaxprocs;
+ runtime·sched.mcpumax = runtime·gomaxprocs;
matchmg();
runtime·unlock(&runtime·sched);
}
}
// ran out of deferred calls - old-school panic now
+ runtime·startpanic();
printpanics(g->panic);
runtime·dopanic(0);
}
int32 ret;
runtime·lock(&runtime·sched);
- ret = runtime·sched.gomaxprocs;
+ ret = runtime·gomaxprocs;
if (n <= 0)
n = ret;
- runtime·sched.gomaxprocs = n;
+ runtime·gomaxprocs = n;
runtime·sched.mcpumax = n;
// handle fewer procs?
if(runtime·sched.mcpu > runtime·sched.mcpumax) {
maxround = sizeof(uintptr),
};
-int32 runtime·panicking = 0;
+uint32 runtime·panicking;
int32
runtime·gotraceback(void)
return runtime·atoi(p);
}
+static Lock paniclk;
+
void
-runtime·dopanic(int32 unused)
+runtime·startpanic(void)
{
- if(runtime·panicking) {
- runtime·printf("double panic\n");
+ if(m->dying) {
+ runtime·printf("panic during panic\n");
runtime·exit(3);
}
- runtime·panicking++;
+ m->dying = 1;
+ runtime·xadd(&runtime·panicking, 1);
+ runtime·lock(&paniclk);
+}
+
+void
+runtime·dopanic(int32 unused)
+{
+ static bool didothers;
if(g->sig != 0)
runtime·printf("\n[signal %x code=%p addr=%p pc=%p]\n",
runtime·printf("\n");
if(runtime·gotraceback()){
runtime·traceback(runtime·getcallerpc(&unused), runtime·getcallersp(&unused), 0, g);
- runtime·tracebackothers(g);
+ if(!didothers) {
+ didothers = true;
+ runtime·tracebackothers(g);
+ }
}
-
+ runtime·unlock(&paniclk);
+ if(runtime·xadd(&runtime·panicking, -1) != 0) {
+ // Some other m is panicking too.
+ // Let it print what it needs to print.
+ // Wait forever without chewing up cpu.
+ // It will exit when it's done.
+ static Lock deadlock;
+ runtime·lock(&deadlock);
+ runtime·lock(&deadlock);
+ }
+
+ runtime·panicking = 1; // so we don't dump another stack trace for breakpoint trap
runtime·breakpoint(); // so we can grab it in a debugger
runtime·exit(2);
}
void
runtime·throw(int8 *s)
{
+ runtime·startpanic();
runtime·printf("throw: %s\n", s);
runtime·dopanic(0);
*(int32*)0 = 0; // not reached
int32 locks;
int32 nomemprof;
int32 waitnextg;
+ int32 dying;
Note havenextg;
G* nextg;
M* alllink; // on allm
M* runtime·allm;
int32 runtime·goidgen;
extern int32 runtime·gomaxprocs;
-extern int32 runtime·panicking;
+extern uint32 runtime·panicking;
extern int32 runtime·gcwaiting; // gc is waiting to run
int8* runtime·goos;
extern bool runtime·iscgo;
int32 runtime·callers(int32, uintptr*, int32);
int64 runtime·nanotime(void);
void runtime·dopanic(int32);
+void runtime·startpanic(void);
#pragma varargck argpos runtime·printf 1
#pragma varargck type "d" int32