| // Copyright 2014 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. |
| |
| package runtime |
| #include "runtime.h" |
| #include "arch_GOARCH.h" |
| #include "malloc.h" |
| #include "stack.h" |
| #include "../../cmd/ld/textflag.h" |
| |
| // This file contains functions called by Go but written |
| // in C. These functions are problematic for the garbage |
| // collector and stack copier because we don't have |
| // stack maps for them. So we must ensure that the |
| // garbage collector and stack copier cannot see these |
| // frames. So we impose the following invariants: |
| |
| // 1) Functions should be marked NOSPLIT and call |
| // out to only NOSPLIT functions (recursively). |
| // 2) Functions should not block. |
| |
| // These invariants do not hold yet but will be established once we have |
| // finished converting runtime support code from C to Go. |
| |
| #pragma textflag NOSPLIT |
| func golock(p *Lock) { |
| runtime·lock(p); |
| } |
| #pragma textflag NOSPLIT |
| func gounlock(p *Lock) { |
| runtime·unlock(p); |
| } |
| |
| #pragma textflag NOSPLIT |
| func goreadgogc() (r int32) { |
| r = runtime·readgogc(); |
| } |
| |
| // entry point for testing |
| // TODO: mcall and run on M stack |
| func gostringW(str Slice) (s String) { |
| s = runtime·gostringw((uint16*)str.array); |
| } |
| |
| #pragma textflag NOSPLIT |
| func gonanotime() (r int64) { |
| r = runtime·nanotime(); |
| } |
| |
| #pragma textflag NOSPLIT |
| func goatomicloadp(p **byte) (v *byte) { |
| v = runtime·atomicloadp(p); |
| } |
| |
| #pragma textflag NOSPLIT |
| func goatomicstorep(p **byte, v *byte) { |
| runtime·atomicstorep(p, v); |
| } |
| |
| #pragma textflag NOSPLIT |
| func runtime·gocas(p *uint32, x uint32, y uint32) (ret bool) { |
| ret = runtime·cas(p, x, y); |
| } |
| |
| #pragma textflag NOSPLIT |
| func runtime·gocasx(p *uintptr, x uintptr, y uintptr) (ret bool) { |
| ret = runtime·casp((void**)p, (void*)x, (void*)y); |
| } |
| |
| #pragma textflag NOSPLIT |
| func runtime·acquirem() (ret *M) { |
| ret = g->m; |
| ret->locks++; |
| } |
| |
| #pragma textflag NOSPLIT |
| func runtime·releasem(mp *M) { |
| mp->locks--; |
| if(mp->locks == 0 && g->preempt) { |
| // restore the preemption request in case we've cleared it in newstack |
| g->stackguard0 = StackPreempt; |
| } |
| } |
| |
| #pragma textflag NOSPLIT |
| func runtime·gomcache() (ret *MCache) { |
| ret = g->m->mcache; |
| } |
| |
| // For testing. |
| // TODO: find a better place for this. |
| func GCMask(x Eface) (mask Slice) { |
| runtime·getgcmask(x.data, x.type, &mask.array, &mask.len); |
| mask.cap = mask.len; |
| } |
| |
| #pragma textflag NOSPLIT |
| func gopersistentalloc(size uintptr) (x *void) { |
| // TODO: used only for itabs for now. Need to make &mstats.other_sys arg parameterized. |
| x = runtime·persistentalloc(size, 0, &mstats.other_sys); |
| } |
| |
| #pragma textflag NOSPLIT |
| func reflect·typelinks() (ret Slice) { |
| extern Type *typelink[], *etypelink[]; |
| ret.array = (byte*)typelink; |
| ret.len = etypelink - typelink; |
| ret.cap = ret.len; |
| } |