// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. /* * basic types */ typedef signed char int8; typedef unsigned char uint8; typedef signed short int16; typedef unsigned short uint16; typedef signed int int32; typedef unsigned int uint32; typedef signed long long int int64; typedef unsigned long long int uint64; typedef float float32; typedef double float64; #ifdef _64BIT typedef uint64 uintptr; typedef int64 intptr; #else typedef uint32 uintptr; typedef int32 intptr; #endif /* * get rid of C types * the / / / forces a syntax error immediately, * which will show "last name: XXunsigned". */ #define unsigned XXunsigned / / / #define signed XXsigned / / / #define char XXchar / / / #define short XXshort / / / #define int XXint / / / #define long XXlong / / / #define float XXfloat / / / #define double XXdouble / / / /* * defined types */ typedef uint8 bool; typedef uint8 byte; typedef struct Alg Alg; typedef struct Func Func; typedef struct G G; typedef struct Gobuf Gobuf; typedef struct Lock Lock; typedef struct M M; typedef struct Mem Mem; typedef union Note Note; typedef struct Slice Slice; typedef struct Stktop Stktop; typedef struct String String; typedef struct Usema Usema; typedef struct SigTab SigTab; typedef struct MCache MCache; typedef struct Iface Iface; typedef struct Itab Itab; typedef struct Eface Eface; typedef struct Type Type; typedef struct Defer Defer; typedef struct hash Hmap; typedef struct Hchan Hchan; typedef struct Complex64 Complex64; typedef struct Complex128 Complex128; /* * per-cpu declaration. * "extern register" is a special storage class implemented by 6c, 8c, etc. * on machines with lots of registers, it allocates a register that will not be * used in generated code. on the x86, it allocates a slot indexed by a * segment register. * * amd64: allocated downwards from R15 * x86: allocated upwards from 0(FS) * arm: allocated downwards from R10 * * every C file linked into a Go program must include runtime.h * so that the C compiler knows to avoid other uses of these registers. * the Go compilers know to avoid them. */ extern register G* g; extern register M* m; /* * defined constants */ enum { // G status Gidle, Grunnable, Grunning, Gsyscall, Gwaiting, Gmoribund, Gdead, }; enum { true = 1, false = 0, }; /* * structures */ struct Lock { uint32 key; #ifdef __MINGW__ void* event; #else uint32 sema; // for OS X #endif }; struct Usema { uint32 u; uint32 k; }; union Note { struct { // Linux Lock lock; }; struct { // OS X int32 wakeup; Usema sema; }; }; struct String { byte* str; int32 len; }; struct Iface { Itab* tab; void* data; }; struct Eface { Type* type; void* data; }; struct Complex64 { float32 real; float32 imag; }; struct Complex128 { float64 real; float64 imag; }; struct Slice { // must not move anything byte* array; // actual data uint32 len; // number of elements uint32 cap; // allocated number of elements }; struct Gobuf { // The offsets of these fields are known to (hard-coded in) libmach. byte* sp; byte* pc; G* g; }; struct G { byte* stackguard; // cannot move - also known to linker, libmach, libcgo byte* stackbase; // cannot move - also known to libmach, libcgo Defer* defer; Gobuf sched; // cannot move - also known to libmach byte* stack0; byte* entry; // initial function G* alllink; // on allg void* param; // passed parameter on wakeup int16 status; int32 goid; uint32 selgen; // valid sudog pointer G* schedlink; bool readyonstop; M* m; // for debuggers, but offset not hard-coded M* lockedm; void (*cgofn)(void*); // for cgo/ffi void *cgoarg; }; struct M { // The offsets of these fields are known to (hard-coded in) libmach. G* g0; // goroutine with scheduling stack void (*morepc)(void); void* morefp; // frame pointer for more stack Gobuf morebuf; // gobuf arg to morestack // Fields not known to debuggers. uint32 moreframe; // size arguments to morestack uint32 moreargs; uintptr cret; // return value from C uint64 procid; // for debuggers, but offset not hard-coded G* gsignal; // signal-handling G uint32 tls[8]; // thread-local storage (for 386 extern register) Gobuf sched; // scheduling stack G* curg; // current running goroutine int32 id; int32 mallocing; int32 gcing; int32 locks; int32 waitnextg; Note havenextg; G* nextg; M* alllink; // on allm M* schedlink; uint32 machport; // Return address for Mach IPC (OS X) MCache *mcache; G* lockedg; #ifdef __MINGW__ void* return_address; // saved return address and stack void* stack_pointer; // pointer for Windows stdcall void* os_stack_pointer; #endif }; struct Stktop { // The offsets of these fields are known to (hard-coded in) libmach. uint8* stackguard; uint8* stackbase; Gobuf gobuf; uint32 args; // Frame pointer: where args start in old frame. // fp == gobuf.sp except in the case of a reflected // function call, which uses an off-stack argument frame. uint8* fp; }; struct Alg { uintptr (*hash)(uint32, void*); uint32 (*equal)(uint32, void*, void*); void (*print)(uint32, void*); void (*copy)(uint32, void*, void*); }; struct SigTab { int32 flags; int8 *name; }; enum { SigCatch = 1<<0, SigIgnore = 1<<1, SigRestart = 1<<2, SigQueue = 1<<3, }; // (will be) shared with go; edit ../cmd/6g/sys.go too. // should move out of sys.go eventually. // also eventually, the loaded symbol table should // be closer to this form. struct Func { String name; String type; // go type string String src; // src file name uint64 entry; // entry pc int64 frame; // stack frame size Slice pcln; // pc/ln tab for this func int64 pc0; // starting pc, ln for table int32 ln0; int32 args; // number of 32-bit in/out args int32 locals; // number of 32-bit locals }; /* * defined macros * you need super-goru privilege * to add this list. */ #define nelem(x) (sizeof(x)/sizeof((x)[0])) #define nil ((void*)0) /* * known to compiler */ enum { AMEM, ANOEQ, ASTRING, AINTER, ANILINTER, AFAKE, Amax }; enum { Structrnd = sizeof(uintptr) }; /* * deferred subroutine calls */ struct Defer { int32 siz; byte* sp; byte* fn; Defer* link; byte args[8]; // padded to actual size }; /* * external data */ extern Alg algarray[Amax]; extern String emptystring; G* allg; M* allm; int32 goidgen; extern int32 gomaxprocs; extern int32 panicking; extern int32 maxround; extern int32 fd; // usually 1; set to 2 when panicking extern int32 gcwaiting; // gc is waiting to run int8* goos; /* * common functions and data */ int32 strcmp(byte*, byte*); int32 findnull(byte*); int32 findnullw(uint16*); void dump(byte*, int32); int32 runetochar(byte*, int32); int32 charntorune(int32*, uint8*, int32); /* * very low level c-called */ void gogo(Gobuf*, uintptr); void gogocall(Gobuf*, void(*)(void)); uintptr gosave(Gobuf*); void ·lessstack(void); void goargs(void); void FLUSH(void*); void* getu(void); void throw(int8*); uint32 rnd(uint32, uint32); void prints(int8*); void printf(int8*, ...); byte* mchr(byte*, byte, byte*); void mcpy(byte*, byte*, uint32); int32 mcmp(byte*, byte*, uint32); void memmove(void*, void*, uint32); void* mal(uintptr); void* malx(uintptr size, int32 skip_delta); uint32 cmpstring(String, String); String gostring(byte*); String gostringw(uint16*); void initsig(void); int32 gotraceback(void); void traceback(uint8 *pc, uint8 *sp, G* gp); void tracebackothers(G*); int32 open(byte*, int32, ...); int32 write(int32, void*, int32); bool cas(uint32*, uint32, uint32); bool casp(void**, void*, void*); uint32 xadd(uint32 volatile*, int32); void jmpdefer(byte*, void*); void exit1(int32); void ready(G*); byte* getenv(int8*); int32 atoi(byte*); void newosproc(M *m, G *g, void *stk, void (*fn)(void)); void signalstack(byte*, int32); G* malg(int32); void minit(void); Func* findfunc(uintptr); int32 funcline(Func*, uint64); void* stackalloc(uint32); void stackfree(void*); MCache* allocmcache(void); void mallocinit(void); bool ifaceeq(Iface, Iface); bool efaceeq(Eface, Eface); uintptr ifacehash(Iface); uintptr efacehash(Eface); uintptr nohash(uint32, void*); uint32 noequal(uint32, void*, void*); void* malloc(uintptr size); void free(void *v); void addfinalizer(void*, void(*fn)(void*), int32); void exit(int32); void breakpoint(void); void gosched(void); void goexit(void); void runcgo(void (*fn)(void*), void*); void ·entersyscall(void); void ·exitsyscall(void); void newproc1(byte*, byte*, int32, int32); void siginit(void); bool sigsend(int32 sig); void gettime(int64*, int32*); int32 callers(int32, uintptr*, int32); int64 nanotime(void); #pragma varargck argpos printf 1 #pragma varargck type "d" int32 #pragma varargck type "d" uint32 #pragma varargck type "D" int64 #pragma varargck type "D" uint64 #pragma varargck type "x" int32 #pragma varargck type "x" uint32 #pragma varargck type "X" int64 #pragma varargck type "X" uint64 #pragma varargck type "p" void* #pragma varargck type "p" uintptr #pragma varargck type "s" int8* #pragma varargck type "s" uint8* #pragma varargck type "S" String // TODO(rsc): Remove. These are only temporary, // for the mark and sweep collector. void stoptheworld(void); void starttheworld(void); /* * mutual exclusion locks. in the uncontended case, * as fast as spin locks (just a few user-level instructions), * but on the contention path they sleep in the kernel. * a zeroed Lock is unlocked (no need to initialize each lock). */ void lock(Lock*); void unlock(Lock*); void destroylock(Lock*); /* * sleep and wakeup on one-time events. * before any calls to notesleep or notewakeup, * must call noteclear to initialize the Note. * then, any number of threads can call notesleep * and exactly one thread can call notewakeup (once). * once notewakeup has been called, all the notesleeps * will return. future notesleeps will return immediately. */ void noteclear(Note*); void notesleep(Note*); void notewakeup(Note*); /* * Redefine methods for the benefit of gcc, which does not support * UTF-8 characters in identifiers. */ #ifndef __GNUC__ #define runtime_memclr ·memclr #define runtime_getcallerpc ·getcallerpc #define runtime_mmap ·mmap #define runtime_printslice ·printslice #define runtime_printbool ·printbool #define runtime_printfloat ·printfloat #define runtime_printhex ·printhex #define runtime_printint ·printint #define runtime_printiface ·printiface #define runtime_printeface ·printeface #define runtime_printpc ·printpc #define runtime_printpointer ·printpointer #define runtime_printstring ·printstring #define runtime_printuint ·printuint #define runtime_printcomplex ·printcomplex #define runtime_setcallerpc ·setcallerpc #endif /* * This is consistent across Linux and BSD. * If a new OS is added that is different, move this to * $GOOS/$GOARCH/defs.h. */ #define EACCES 13 /* * low level go-called */ uint8* runtime_mmap(byte*, uint32, int32, int32, int32, uint32); void runtime_memclr(byte*, uint32); void runtime_setcallerpc(void*, void*); void* runtime_getcallerpc(void*); /* * runtime go-called */ void runtime_printbool(bool); void runtime_printfloat(float64); void runtime_printint(int64); void runtime_printiface(Iface); void runtime_printeface(Eface); void runtime_printstring(String); void runtime_printpc(void*); void runtime_printpointer(void*); void runtime_printuint(uint64); void runtime_printhex(uint64); void runtime_printslice(Slice); void runtime_printcomplex(Complex128); void ·panicl(int32); /* * wrapped for go users */ float64 Inf(int32 sign); float64 NaN(void); float32 float32frombits(uint32 i); uint32 float32tobits(float32 f); float64 float64frombits(uint64 i); uint64 float64tobits(float64 f); float64 frexp(float64 d, int32 *ep); bool isInf(float64 f, int32 sign); bool isNaN(float64 f); float64 ldexp(float64 d, int32 e); float64 modf(float64 d, float64 *ip); void semacquire(uint32*); void semrelease(uint32*); String signame(int32 sig); void mapassign(Hmap*, byte*, byte*); void mapaccess(Hmap*, byte*, byte*, bool*); struct hash_iter* mapiterinit(Hmap*); void mapiternext(struct hash_iter*); bool mapiterkey(struct hash_iter*, void*); void mapiterkeyvalue(struct hash_iter*, void*, void*); Hmap* makemap(Type*, Type*, uint32); Hchan* makechan(Type*, uint32); void chansend(Hchan*, void*, bool*); void chanrecv(Hchan*, void*, bool*); void chanclose(Hchan*); bool chanclosed(Hchan*); int32 chanlen(Hchan*); int32 chancap(Hchan*); void ifaceE2I(struct InterfaceType*, Eface, Iface*);