// Copyright 2010 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 "type.h"

func GOMAXPROCS(n int) (ret int) {
	ret = runtime·gomaxprocsfunc(n);
}

func NumCPU() (ret int) {
	ret = runtime·ncpu;
}

func NumCgoCall() (ret int64) {
	M *mp;

	ret = 0;
	for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
		ret += mp->ncgocall;
}

func newParFor(nthrmax uint32) (desc *ParFor) {
	desc = runtime·parforalloc(nthrmax);
}

func parForSetup(desc *ParFor, nthr uint32, n uint32, ctx *byte, wait bool, body *byte) {
	runtime·parforsetup(desc, nthr, n, ctx, wait, *(void(**)(ParFor*, uint32))body);
}

func parForDo(desc *ParFor) {
	runtime·parfordo(desc);
}

func parForIters(desc *ParFor, tid uintptr) (start uintptr, end uintptr) {
	runtime·parforiters(desc, tid, &start, &end);
}

func gogoBytes() (x int32) {
	x = RuntimeGogoBytes;
}

func typestring(e Eface) (s String) {
	s = *e.type->string;
}

func golockedOSThread() (ret bool) {
	ret = runtime·lockedOSThread();
}

func NumGoroutine() (ret int) {
	ret = runtime·gcount();
}

func getgoroot() (out String) {
	byte *p;

	p = runtime·getenv("GOROOT");
	out = runtime·gostringnocopy(p);
}

/*
 * We assume that all architectures turn faults and the like
 * into apparent calls to runtime.sigpanic.  If we see a "call"
 * to runtime.sigpanic, we do not back up the PC to find the
 * line number of the CALL instruction, because there is no CALL.
 */
void	runtime·sigpanic(void);

func Caller(skip int) (retpc uintptr, retfile String, retline int, retbool bool) {
	Func *f, *g;
	uintptr pc;
	uintptr rpc[2];

	/*
	 * Ask for two PCs: the one we were asked for
	 * and what it called, so that we can see if it
	 * "called" sigpanic.
	 */
	retpc = 0;
	if(runtime·callers(1+skip-1, rpc, 2) < 2) {
		retfile = runtime·emptystring;
		retline = 0;
		retbool = false;
	} else if((f = runtime·findfunc(rpc[1])) == nil) {
		retfile = runtime·emptystring;
		retline = 0;
		retbool = true;  // have retpc at least
	} else {
		retpc = rpc[1];
		pc = retpc;
		g = runtime·findfunc(rpc[0]);
		if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
			pc--;
		retline = runtime·funcline(f, pc, &retfile);
		retbool = true;
	}
}

func Callers(skip int, pc Slice) (retn int) {
	// runtime.callers uses pc.array==nil as a signal
	// to print a stack trace.  Pick off 0-length pc here
	// so that we don't let a nil pc slice get to it.
	if(pc.len == 0)
		retn = 0;
	else
		retn = runtime·callers(skip, (uintptr*)pc.array, pc.len);
}

func runtime∕pprof·runtime_cyclesPerSecond() (res int64) {
	res = runtime·tickspersecond();
}

func sync·runtime_procPin() (p int) {
	M *mp;

	mp = m;
	// Disable preemption.
	mp->locks++;
	p = mp->p->id;
}

func sync·runtime_procUnpin() {
	m->locks--;
}
