Commit 193daab9 authored by Russ Cox's avatar Russ Cox

cmd/cc, cmd/ld, runtime: disallow conservative data/bss objects

In linker, refuse to write conservative (array of pointers) as the
garbage collection type for any variable in the data/bss GC program.

In the linker, attach the Go type to an already-read C declaration
during dedup. This gives us Go types for C globals for free as long
as the cmd/dist-generated Go code contains the declaration.
(Most runtime C declarations have a corresponding Go declaration.
Both are bss declarations and so the linker dedups them.)

In cmd/dist, add a few more C files to the auto-Go-declaration list
in order to get Go type information for the C declarations into the linker.

In C compiler, mark all non-pointer-containing global declarations
and all string data as NOPTR. This allows them to exist in C files
without any corresponding Go declaration. Count C function pointers
as "non-pointer-containing", since we have no heap-allocated C functions.

In runtime, add NOPTR to the remaining pointer-containing declarations,
none of which refer to Go heap objects.

In runtime, also move os.Args and syscall.envs data into runtime-owned
variables. Otherwise, in programs that do not import os or syscall, the
runtime variables named os.Args and syscall.envs will be missing type
information.

I believe that this CL eliminates the final source of conservative GC scanning
in non-SWIG Go programs, and therefore...

Fixes #909.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/149770043
parent 5917692b
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
#include <u.h> #include <u.h>
#include "cc.h" #include "cc.h"
#include "../ld/textflag.h"
static int haspointers(Type*);
Node* Node*
dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n) dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n)
...@@ -123,7 +126,8 @@ loop: ...@@ -123,7 +126,8 @@ loop:
if(dataflag) { if(dataflag) {
s->dataflag = dataflag; s->dataflag = dataflag;
dataflag = 0; dataflag = 0;
} } else if(s->type != T && !haspointers(s->type))
s->dataflag = NOPTR;
firstbit = 0; firstbit = 0;
n->sym = s; n->sym = s;
n->type = s->type; n->type = s->type;
...@@ -568,9 +572,8 @@ haspointers(Type *t) ...@@ -568,9 +572,8 @@ haspointers(Type *t)
return 0; return 0;
case TARRAY: case TARRAY:
return haspointers(t->link); return haspointers(t->link);
case TFUNC:
case TIND: case TIND:
return 1; return t->link->etype != TFUNC;
default: default:
return 0; return 0;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <u.h> #include <u.h>
#include "cc.h" #include "cc.h"
#include "y.tab.h" #include "y.tab.h"
#include "../ld/textflag.h"
#ifndef CPP #ifndef CPP
#define CPP "cpp" #define CPP "cpp"
...@@ -1317,6 +1318,7 @@ cinit(void) ...@@ -1317,6 +1318,7 @@ cinit(void)
t->width = 0; t->width = 0;
symstring = slookup(".string"); symstring = slookup(".string");
symstring->class = CSTATIC; symstring->class = CSTATIC;
symstring->dataflag = NOPTR;
symstring->type = t; symstring->type = t;
t = typ(TARRAY, types[TCHAR]); t = typ(TARRAY, types[TCHAR]);
......
...@@ -129,6 +129,7 @@ func (p *Package) writeDefs() { ...@@ -129,6 +129,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle) fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C) fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
} else { } else {
fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C) fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
} }
fmt.Fprintf(fc, "\n") fmt.Fprintf(fc, "\n")
...@@ -397,6 +398,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { ...@@ -397,6 +398,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
// C wrapper calls into gcc, passing a pointer to the argument frame. // C wrapper calls into gcc, passing a pointer to the argument frame.
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname) fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
fmt.Fprintf(fc, "void %s(void*);\n", cname) fmt.Fprintf(fc, "void %s(void*);\n", cname)
fmt.Fprintf(fc, "#pragma dataflag NOPTR\n")
fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname) fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
nret := 0 nret := 0
...@@ -1151,20 +1153,31 @@ void *_CMalloc(size_t); ...@@ -1151,20 +1153,31 @@ void *_CMalloc(size_t);
const cProlog = ` const cProlog = `
#include "runtime.h" #include "runtime.h"
#include "cgocall.h" #include "cgocall.h"
#include "textflag.h"
#pragma dataflag NOPTR
static void *cgocall_errno = runtime·cgocall_errno; static void *cgocall_errno = runtime·cgocall_errno;
#pragma dataflag NOPTR
void *·_cgo_runtime_cgocall_errno = &cgocall_errno; void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
#pragma dataflag NOPTR
static void *runtime_gostring = runtime·gostring; static void *runtime_gostring = runtime·gostring;
#pragma dataflag NOPTR
void *·_cgo_runtime_gostring = &runtime_gostring; void *·_cgo_runtime_gostring = &runtime_gostring;
#pragma dataflag NOPTR
static void *runtime_gostringn = runtime·gostringn; static void *runtime_gostringn = runtime·gostringn;
#pragma dataflag NOPTR
void *·_cgo_runtime_gostringn = &runtime_gostringn; void *·_cgo_runtime_gostringn = &runtime_gostringn;
#pragma dataflag NOPTR
static void *runtime_gobytes = runtime·gobytes; static void *runtime_gobytes = runtime·gobytes;
#pragma dataflag NOPTR
void *·_cgo_runtime_gobytes = &runtime_gobytes; void *·_cgo_runtime_gobytes = &runtime_gobytes;
#pragma dataflag NOPTR
static void *runtime_cmalloc = runtime·cmalloc; static void *runtime_cmalloc = runtime·cmalloc;
#pragma dataflag NOPTR
void *·_cgo_runtime_cmalloc = &runtime_cmalloc; void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
void ·_Cerrno(void*, int32); void ·_Cerrno(void*, int32);
......
...@@ -330,9 +330,11 @@ mkzsys(char *dir, char *file) ...@@ -330,9 +330,11 @@ mkzsys(char *dir, char *file)
static char *runtimedefs[] = { static char *runtimedefs[] = {
"defs.c", "defs.c",
"malloc.c", "malloc.c",
"mcache.c",
"mgc0.c", "mgc0.c",
"proc.c", "proc.c",
"parfor.c", "parfor.c",
"stack.c",
}; };
// mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h, // mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
......
...@@ -818,6 +818,7 @@ proggenaddsym(ProgGen *g, LSym *s) ...@@ -818,6 +818,7 @@ proggenaddsym(ProgGen *g, LSym *s)
if(s->gotype == nil && s->size >= PtrSize) { if(s->gotype == nil && s->size >= PtrSize) {
// conservative scan // conservative scan
diag("missing Go type information for global symbol: %s", s->name);
if((s->size%PtrSize) || (g->pos%PtrSize)) if((s->size%PtrSize) || (g->pos%PtrSize))
diag("proggenaddsym: unaligned conservative symbol %s: size=%lld pos=%lld", diag("proggenaddsym: unaligned conservative symbol %s: size=%lld pos=%lld",
s->name, s->size, g->pos); s->name, s->size, g->pos);
......
...@@ -550,7 +550,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn) ...@@ -550,7 +550,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
static int ndup; static int ndup;
char *name; char *name;
Reloc *r; Reloc *r;
LSym *s, *dup; LSym *s, *dup, *typ;
Pcln *pc; Pcln *pc;
Auto *a; Auto *a;
...@@ -586,7 +586,9 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn) ...@@ -586,7 +586,9 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
s->type = t; s->type = t;
if(s->size < size) if(s->size < size)
s->size = size; s->size = size;
s->gotype = rdsym(ctxt, f, pkg); typ = rdsym(ctxt, f, pkg);
if(typ != nil) // if bss sym defined multiple times, take type from any one def
s->gotype = typ;
rddata(f, &s->p, &s->np); rddata(f, &s->p, &s->np);
s->maxp = s->np; s->maxp = s->np;
n = rdint(f); n = rdint(f);
......
...@@ -11,6 +11,12 @@ import "syscall" ...@@ -11,6 +11,12 @@ import "syscall"
// Args hold the command-line arguments, starting with the program name. // Args hold the command-line arguments, starting with the program name.
var Args []string var Args []string
func init() {
Args = runtime_args()
}
func runtime_args() []string // in package runtime
// Getuid returns the numeric user id of the caller. // Getuid returns the numeric user id of the caller.
func Getuid() int { return syscall.Getuid() } func Getuid() int { return syscall.Getuid() }
......
...@@ -903,8 +903,6 @@ TEXT runtime·emptyfunc(SB),0,$0-0 ...@@ -903,8 +903,6 @@ TEXT runtime·emptyfunc(SB),0,$0-0
TEXT runtime·abort(SB),NOSPLIT,$0-0 TEXT runtime·abort(SB),NOSPLIT,$0-0
INT $0x3 INT $0x3
GLOBL runtime·tls0(SB), $32
// hash function using AES hardware instructions // hash function using AES hardware instructions
TEXT runtime·aeshash(SB),NOSPLIT,$0-16 TEXT runtime·aeshash(SB),NOSPLIT,$0-16
MOVL p+0(FP), AX // ptr to data MOVL p+0(FP), AX // ptr to data
......
...@@ -871,8 +871,6 @@ TEXT runtime·gocputicks(SB),NOSPLIT,$0-8 ...@@ -871,8 +871,6 @@ TEXT runtime·gocputicks(SB),NOSPLIT,$0-8
MOVQ AX, ret+0(FP) MOVQ AX, ret+0(FP)
RET RET
GLOBL runtime·tls0(SB), $64
// hash function using AES hardware instructions // hash function using AES hardware instructions
TEXT runtime·aeshash(SB),NOSPLIT,$0-32 TEXT runtime·aeshash(SB),NOSPLIT,$0-32
MOVQ p+0(FP), AX // ptr to data MOVQ p+0(FP), AX // ptr to data
......
...@@ -674,8 +674,6 @@ TEXT runtime·gocputicks(SB),NOSPLIT,$0-8 ...@@ -674,8 +674,6 @@ TEXT runtime·gocputicks(SB),NOSPLIT,$0-8
MOVQ AX, ret+0(FP) MOVQ AX, ret+0(FP)
RET RET
GLOBL runtime·tls0(SB), $64
// hash function using AES hardware instructions // hash function using AES hardware instructions
// For now, our one amd64p32 system (NaCl) does not // For now, our one amd64p32 system (NaCl) does not
// support using AES instructions, so have not bothered to // support using AES instructions, so have not bothered to
......
...@@ -59,6 +59,8 @@ static BitVector makeheapobjbv(byte *p, uintptr size); ...@@ -59,6 +59,8 @@ static BitVector makeheapobjbv(byte *p, uintptr size);
// fd to write the dump to. // fd to write the dump to.
static uintptr dumpfd; static uintptr dumpfd;
#pragma dataflag NOPTR /* tmpbuf not a heap pointer at least */
static byte *tmpbuf; static byte *tmpbuf;
static uintptr tmpbufsize; static uintptr tmpbufsize;
...@@ -109,6 +111,7 @@ typedef struct TypeCacheBucket TypeCacheBucket; ...@@ -109,6 +111,7 @@ typedef struct TypeCacheBucket TypeCacheBucket;
struct TypeCacheBucket { struct TypeCacheBucket {
Type *t[TypeCacheAssoc]; Type *t[TypeCacheAssoc];
}; };
#pragma dataflag NOPTR /* only initialized and used while world is stopped */
static TypeCacheBucket typecache[TypeCacheBuckets]; static TypeCacheBucket typecache[TypeCacheBuckets];
// dump a uint64 in a varint format parseable by encoding/binary // dump a uint64 in a varint format parseable by encoding/binary
......
...@@ -329,29 +329,6 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n) ...@@ -329,29 +329,6 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
return p; return p;
} }
// Runtime stubs.
static void*
cnew(Type *typ, intgo n)
{
if(n < 0 || (typ->size > 0 && n > MaxMem/typ->size))
runtime·throw("runtime: allocation size out of range");
return runtime·mallocgc(typ->size*n, typ, typ->kind&KindNoPointers ? FlagNoScan : 0);
}
// same as runtime·new, but callable from C
void*
runtime·cnew(Type *typ)
{
return cnew(typ, 1);
}
void*
runtime·cnewarray(Type *typ, intgo n)
{
return cnew(typ, n);
}
void void
runtime·setFinalizer_m(void) runtime·setFinalizer_m(void)
{ {
......
...@@ -526,8 +526,6 @@ uintptr runtime·sweepone(void); ...@@ -526,8 +526,6 @@ uintptr runtime·sweepone(void);
void runtime·markspan(void *v, uintptr size, uintptr n, bool leftover); void runtime·markspan(void *v, uintptr size, uintptr n, bool leftover);
void runtime·unmarkspan(void *v, uintptr size); void runtime·unmarkspan(void *v, uintptr size);
void runtime·purgecachedstats(MCache*); void runtime·purgecachedstats(MCache*);
void* runtime·cnew(Type*);
void* runtime·cnewarray(Type*, intgo);
void runtime·tracealloc(void*, uintptr, Type*); void runtime·tracealloc(void*, uintptr, Type*);
void runtime·tracefree(void*, uintptr); void runtime·tracefree(void*, uintptr);
void runtime·tracegc(void); void runtime·tracegc(void);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
extern volatile intgo runtime·MemProfileRate; extern volatile intgo runtime·MemProfileRate;
// dummy MSpan that contains no free objects. // dummy MSpan that contains no free objects.
static MSpan runtime·emptymspan; MSpan runtime·emptymspan;
MCache* MCache*
runtime·allocmcache(void) runtime·allocmcache(void)
......
...@@ -120,7 +120,7 @@ FinBlock* runtime·finc; // cache of free blocks ...@@ -120,7 +120,7 @@ FinBlock* runtime·finc; // cache of free blocks
static byte finptrmask[FinBlockSize/PtrSize/PointersPerByte]; static byte finptrmask[FinBlockSize/PtrSize/PointersPerByte];
bool runtime·fingwait; bool runtime·fingwait;
bool runtime·fingwake; bool runtime·fingwake;
static FinBlock *runtime·allfin; // list of all blocks FinBlock *runtime·allfin; // list of all blocks
BitVector runtime·gcdatamask; BitVector runtime·gcdatamask;
BitVector runtime·gcbssmask; BitVector runtime·gcbssmask;
...@@ -140,7 +140,7 @@ static BitVector unrollglobgcprog(byte *prog, uintptr size); ...@@ -140,7 +140,7 @@ static BitVector unrollglobgcprog(byte *prog, uintptr size);
void runtime·bgsweep(void); void runtime·bgsweep(void);
static FuncVal bgsweepv = {runtime·bgsweep}; static FuncVal bgsweepv = {runtime·bgsweep};
static struct { struct {
uint64 full; // lock-free list of full blocks uint64 full; // lock-free list of full blocks
uint64 empty; // lock-free list of empty blocks uint64 empty; // lock-free list of empty blocks
byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait
...@@ -1038,7 +1038,6 @@ runtime·MSpan_Sweep(MSpan *s, bool preserve) ...@@ -1038,7 +1038,6 @@ runtime·MSpan_Sweep(MSpan *s, bool preserve)
// State of background runtime·sweep. // State of background runtime·sweep.
// Protected by runtime·gclock. // Protected by runtime·gclock.
// Must match mgc0.go.
struct struct
{ {
G* g; G* g;
......
...@@ -147,7 +147,7 @@ runtime·get_random_data(byte **rnd, int32 *rnd_len) ...@@ -147,7 +147,7 @@ runtime·get_random_data(byte **rnd, int32 *rnd_len)
void void
runtime·goenvs(void) runtime·goenvs(void)
{ {
extern Slice syscall·envs; extern Slice runtime·envs;
uint16 *env; uint16 *env;
String *s; String *s;
...@@ -160,8 +160,8 @@ runtime·goenvs(void) ...@@ -160,8 +160,8 @@ runtime·goenvs(void)
for(p=env; *p; n++) for(p=env; *p; n++)
p += runtime·findnullw(p)+1; p += runtime·findnullw(p)+1;
syscall·envs = runtime·makeStringSlice(n); runtime·envs = runtime·makeStringSlice(n);
s = (String*)syscall·envs.array; s = (String*)runtime·envs.array;
p = env; p = env;
for(i=0; i<n; i++) { for(i=0; i<n; i++) {
......
...@@ -102,9 +102,9 @@ extern String runtime·buildVersion; ...@@ -102,9 +102,9 @@ extern String runtime·buildVersion;
#pragma cgo_export_static main #pragma cgo_export_static main
// Filled in by dynamic linker when Cgo is available. // Filled in by dynamic linker when Cgo is available.
void* _cgo_init; void (*_cgo_init)(void);
void* _cgo_malloc; void (*_cgo_malloc)(void);
void* _cgo_free; void (*_cgo_free)(void);
// Copy for Go code. // Copy for Go code.
void* runtime·cgoMalloc; void* runtime·cgoMalloc;
...@@ -852,24 +852,19 @@ struct CgoThreadStart ...@@ -852,24 +852,19 @@ struct CgoThreadStart
void (*fn)(void); void (*fn)(void);
}; };
M *runtime·newM(void); // in proc.go
// Allocate a new m unassociated with any thread. // Allocate a new m unassociated with any thread.
// Can use p for allocation context if needed. // Can use p for allocation context if needed.
M* M*
runtime·allocm(P *p) runtime·allocm(P *p)
{ {
M *mp; M *mp;
static Type *mtype; // The Go type M
g->m->locks++; // disable GC because it can be called from sysmon g->m->locks++; // disable GC because it can be called from sysmon
if(g->m->p == nil) if(g->m->p == nil)
acquirep(p); // temporarily borrow p for mallocs in this function acquirep(p); // temporarily borrow p for mallocs in this function
if(mtype == nil) { mp = runtime·newM();
Eface e;
runtime·gc_m_ptr(&e);
mtype = ((PtrType*)e.type)->elem;
}
mp = runtime·cnew(mtype);
mcommoninit(mp); mcommoninit(mp);
// In case of cgo or Solaris, pthread_create will make us a stack. // In case of cgo or Solaris, pthread_create will make us a stack.
...@@ -889,19 +884,12 @@ runtime·allocm(P *p) ...@@ -889,19 +884,12 @@ runtime·allocm(P *p)
return mp; return mp;
} }
G *runtime·newG(void); // in proc.go
static G* static G*
allocg(void) allocg(void)
{ {
G *gp; return runtime·newG();
static Type *gtype;
if(gtype == nil) {
Eface e;
runtime·gc_g_ptr(&e);
gtype = ((PtrType*)e.type)->elem;
}
gp = runtime·cnew(gtype);
return gp;
} }
static M* lockextra(bool nilokay); static M* lockextra(bool nilokay);
......
...@@ -202,6 +202,14 @@ func newP() *p { ...@@ -202,6 +202,14 @@ func newP() *p {
return new(p) return new(p)
} }
func newM() *m {
return new(m)
}
func newG() *g {
return new(g)
}
func allgadd(gp *g) { func allgadd(gp *g) {
if readgstatus(gp) == _Gidle { if readgstatus(gp) == _Gidle {
gothrow("allgadd: bad status Gidle") gothrow("allgadd: bad status Gidle")
......
...@@ -62,10 +62,12 @@ runtime·mchr(byte *p, byte c, byte *ep) ...@@ -62,10 +62,12 @@ runtime·mchr(byte *p, byte c, byte *ep)
} }
static int32 argc; static int32 argc;
#pragma dataflag NOPTR /* argv not a heap pointer */
static uint8** argv; static uint8** argv;
Slice os·Args; extern Slice runtime·argslice;
Slice syscall·envs; extern Slice runtime·envs;
void (*runtime·sysargs)(int32, uint8**); void (*runtime·sysargs)(int32, uint8**);
...@@ -97,8 +99,8 @@ runtime·goargs(void) ...@@ -97,8 +99,8 @@ runtime·goargs(void)
if(Windows) if(Windows)
return; return;
os·Args = runtime·makeStringSlice(argc); runtime·argslice = runtime·makeStringSlice(argc);
s = (String*)os·Args.array; s = (String*)runtime·argslice.array;
for(i=0; i<argc; i++) for(i=0; i<argc; i++)
s[i] = runtime·gostringnocopy(argv[i]); s[i] = runtime·gostringnocopy(argv[i]);
} }
...@@ -112,8 +114,8 @@ runtime·goenvs_unix(void) ...@@ -112,8 +114,8 @@ runtime·goenvs_unix(void)
for(n=0; argv[argc+1+n] != 0; n++) for(n=0; argv[argc+1+n] != 0; n++)
; ;
syscall·envs = runtime·makeStringSlice(n); runtime·envs = runtime·makeStringSlice(n);
s = (String*)syscall·envs.array; s = (String*)runtime·envs.array;
for(i=0; i<n; i++) for(i=0; i<n; i++)
s[i] = runtime·gostringnocopy(argv[argc+1+i]); s[i] = runtime·gostringnocopy(argv[argc+1+i]);
} }
...@@ -122,7 +124,7 @@ runtime·goenvs_unix(void) ...@@ -122,7 +124,7 @@ runtime·goenvs_unix(void)
Slice Slice
runtime·environ() runtime·environ()
{ {
return syscall·envs; return runtime·envs;
} }
int32 int32
...@@ -267,10 +269,15 @@ runtime·check(void) ...@@ -267,10 +269,15 @@ runtime·check(void)
#pragma dataflag NOPTR #pragma dataflag NOPTR
DebugVars runtime·debug; DebugVars runtime·debug;
static struct { typedef struct DbgVar DbgVar;
struct DbgVar
{
int8* name; int8* name;
int32* value; int32* value;
} dbgvar[] = { };
#pragma dataflag NOPTR /* dbgvar has no heap pointers */
static DbgVar dbgvar[] = {
{"allocfreetrace", &runtime·debug.allocfreetrace}, {"allocfreetrace", &runtime·debug.allocfreetrace},
{"efence", &runtime·debug.efence}, {"efence", &runtime·debug.efence},
{"gctrace", &runtime·debug.gctrace}, {"gctrace", &runtime·debug.gctrace},
......
...@@ -9,6 +9,8 @@ var ticks struct { ...@@ -9,6 +9,8 @@ var ticks struct {
val uint64 val uint64
} }
var tls0 [8]uintptr // available storage for m0's TLS; not necessarily used; opaque to GC
// Note: Called by runtime/pprof in addition to runtime code. // Note: Called by runtime/pprof in addition to runtime code.
func tickspersecond() int64 { func tickspersecond() int64 {
r := int64(atomicload64(&ticks.val)) r := int64(atomicload64(&ticks.val))
...@@ -47,3 +49,12 @@ func parforalloc(nthrmax uint32) *parfor { ...@@ -47,3 +49,12 @@ func parforalloc(nthrmax uint32) *parfor {
nthrmax: nthrmax, nthrmax: nthrmax,
} }
} }
var envs []string
var argslice []string
// called from syscall
func runtime_envs() []string { return envs }
// called from os
func runtime_args() []string { return argslice }
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup", /* 1 */ N+K, "SIGHUP: terminal line hangup",
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup", /* 1 */ N+K, "SIGHUP: terminal line hangup",
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup", /* 1 */ N+K, "SIGHUP: terminal line hangup",
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup", /* 1 */ N+K, "SIGHUP: terminal line hangup",
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup", /* 1 */ N+K, "SIGHUP: terminal line hangup",
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup", /* 1 */ N+K, "SIGHUP: terminal line hangup",
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: terminal line hangup", /* 1 */ N+K, "SIGHUP: terminal line hangup",
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
...@@ -16,6 +18,7 @@ ...@@ -16,6 +18,7 @@
// If you add entries to this table, you must respect the prefix ordering // If you add entries to this table, you must respect the prefix ordering
// and also update the constant values is os_plan9.h. // and also update the constant values is os_plan9.h.
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
// Traps that we cannot be recovered. // Traps that we cannot be recovered.
T, "sys: trap: debug exception", T, "sys: trap: debug exception",
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "textflag.h"
#define N SigNotify #define N SigNotify
#define K SigKill #define K SigKill
#define T SigThrow #define T SigThrow
#define P SigPanic #define P SigPanic
#define D SigDefault #define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = { SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap", /* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: hangup", /* 1 */ N+K, "SIGHUP: hangup",
......
...@@ -32,8 +32,8 @@ enum ...@@ -32,8 +32,8 @@ enum
// Stacks are assigned an order according to size. // Stacks are assigned an order according to size.
// order = log_2(size/FixedStack) // order = log_2(size/FixedStack)
// There is a free list for each order. // There is a free list for each order.
static MSpan runtime·stackpool[NumStackOrders]; MSpan runtime·stackpool[NumStackOrders];
static Mutex runtime·stackpoolmu; Mutex runtime·stackpoolmu;
// TODO: one lock per order? // TODO: one lock per order?
void void
......
...@@ -164,7 +164,7 @@ TEXT runtime·main_init(SB),NOSPLIT,$0-0 ...@@ -164,7 +164,7 @@ TEXT runtime·main_init(SB),NOSPLIT,$0-0
TEXT runtime·main_main(SB),NOSPLIT,$0-0 TEXT runtime·main_main(SB),NOSPLIT,$0-0
JMP main·main(SB) JMP main·main(SB)
TEXT runtime·timenow(SB), NOSPLIT, $0-0 TEXT runtime·timenow(SB),NOSPLIT,$0-0
JMP time·now(SB) JMP time·now(SB)
TEXT sync∕atomic·runtime_procPin(SB),NOSPLIT,$0-0 TEXT sync∕atomic·runtime_procPin(SB),NOSPLIT,$0-0
...@@ -172,3 +172,9 @@ TEXT sync∕atomic·runtime_procPin(SB),NOSPLIT,$0-0 ...@@ -172,3 +172,9 @@ TEXT sync∕atomic·runtime_procPin(SB),NOSPLIT,$0-0
TEXT sync∕atomic·runtime_procUnpin(SB),NOSPLIT,$0-0 TEXT sync∕atomic·runtime_procUnpin(SB),NOSPLIT,$0-0
JMP sync·runtime_procUnpin(SB) JMP sync·runtime_procUnpin(SB)
TEXT syscall·runtime_envs(SB),NOSPLIT,$0-0
JMP runtime·runtime_envs(SB)
TEXT os·runtime_args(SB),NOSPLIT,$0-0
JMP runtime·runtime_args(SB)
...@@ -22,9 +22,11 @@ var ( ...@@ -22,9 +22,11 @@ var (
// envs is provided by the runtime. elements are expected to be // envs is provided by the runtime. elements are expected to be
// of the form "key=value". // of the form "key=value".
envs []string envs []string = runtime_envs()
) )
func runtime_envs() []string // in package runtime
// setenv_c is provided by the runtime, but is a no-op if cgo isn't // setenv_c is provided by the runtime, but is a no-op if cgo isn't
// loaded. // loaded.
func setenv_c(k, v string) func setenv_c(k, v string)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment