From: Russ Cox Date: Tue, 25 Aug 2009 04:16:15 +0000 (-0700) Subject: cgocall bug fix. X-Git-Tag: weekly.2009-11-06~773 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=75a38963ca9144cbbc55ef32c25b020e668eeb40;p=gostls13.git cgocall bug fix. better FFI demo: compute fibonacci numbers using FFI'ed libgmp. R=r DELTA=281 (255 added, 19 deleted, 7 changed) OCL=33815 CL=33820 --- diff --git a/src/libcgo/cgocall.c b/src/libcgo/cgocall.c index c089f1d5d5..d501a38efd 100644 --- a/src/libcgo/cgocall.c +++ b/src/libcgo/cgocall.c @@ -218,25 +218,25 @@ newserver(void) pthread_t p; lock(&cgo.lock); - if(cgo.idle == nil) { - // kick off new servers with work to do - for(w=cgo.whead; w; w=next) { - next = w; - w->next = nil; - f = malloc(sizeof *f); - memset(f, 0, sizeof *f); - f->work = w; - noteclear(&f->note); - notewakeup(&f->note); - if(pthread_create(&p, nil, go_pthread, f) < 0) { - fprintf(stderr, "pthread_create: %s\n", strerror(errno)); - *(int*)0 = 0; - } + // kick off new servers with work to do + for(w=cgo.whead; w; w=next) { + next = w; + w->next = nil; + f = malloc(sizeof *f); + memset(f, 0, sizeof *f); + f->work = w; + noteclear(&f->note); + notewakeup(&f->note); + if(pthread_create(&p, nil, go_pthread, f) < 0) { + fprintf(stderr, "pthread_create: %s\n", strerror(errno)); + *(int*)0 = 0; } - cgo.whead = nil; - cgo.wtail = nil; + } + cgo.whead = nil; + cgo.wtail = nil; - // kick off one more server to sit idle + // kick off one more server to sit idle + if(cgo.idle == nil) { f = malloc(sizeof *f); memset(f, 0, sizeof *f); f->next = cgo.idle; @@ -256,23 +256,41 @@ go_pthread(void *v) CgoServer *f; CgoWork *w; + // newserver queued us; wait for work f = v; + goto wait; + for(;;) { - // wait for work - notesleep(&f->note); + // kick off new server to handle requests while we work + newserver(); // do work w = f->work; w->fn(w->arg); notewakeup(&w->note); + f->work = nil; - // queue f on idle list + // take some work if available + lock(&cgo.lock); + if((w = cgo.whead) != nil) { + cgo.whead = w->next; + if(cgo.whead == nil) + cgo.wtail = nil; + unlock(&cgo.lock); + f->work = w; + continue; + } + + // otherwise queue f->work = nil; noteclear(&f->note); - lock(&cgo.lock); f->next = cgo.idle; cgo.idle = f; unlock(&cgo.lock); + +wait: + // wait for work + notesleep(&f->note); } } diff --git a/usr/rsc/gmp/6c.c b/usr/rsc/gmp/6c.c new file mode 100644 index 0000000000..10d48ad3f5 --- /dev/null +++ b/usr/rsc/gmp/6c.c @@ -0,0 +1,60 @@ +// 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. + +#include "runtime.h" +#include "cgocall.h" + +typedef struct Int Int; +struct Int +{ + void *v; +}; + +// turn on ffi +#pragma dynld initcgo initcgo "libcgo.so" +#pragma dynld cgo cgo "libcgo.so" + +// pull in gmp routines, implemented in gcc.c, from gmp.so + +#pragma dynld gmp_addInt gmp_addInt "gmp.so" +void (*gmp_addInt)(void*); + +#pragma dynld gmp_stringInt gmp_stringInt "gmp.so" +void (*gmp_stringInt)(void*); + +#pragma dynld gmp_newInt gmp_newInt "gmp.so" +void (*gmp_newInt)(void*); + +#pragma dynld c_free free "gmp.so" +void (*c_free)(void*); +void +gmp·addInt(Int *z, Int *x, Int *y, Int *ret) +{ + cgocall(gmp_addInt, &z); +} + +void +gmp·stringInt(Int *z, String ret) +{ + struct { + Int *z; + byte *p; + } a; + a.z = z; + a.p = nil; + cgocall(gmp_stringInt, &a); + ret = gostring(a.p); + cgocall(c_free, a.p); + FLUSH(&ret); +} + +void +gmp·NewInt(uint64 x, Int *z) +{ +if(sizeof(uintptr) != 8) *(int32*)0 = 0; + z = mallocgc(sizeof *z); + FLUSH(&z); + cgocall(gmp_newInt, &x); +} + diff --git a/usr/rsc/gmp/Makefile b/usr/rsc/gmp/Makefile new file mode 100644 index 0000000000..93053d0f4b --- /dev/null +++ b/usr/rsc/gmp/Makefile @@ -0,0 +1,52 @@ +# 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. + +# FFI demo + +include ../../../src/Make.$(GOARCH) + +all: gmp.a gmp.so + +gcc.o: gcc.c + gcc -fPIC -O2 -o gcc.o -c gcc.c + +gmp.so: gcc.o + gcc -shared -o gmp.so gcc.o -L$(GOROOT)/pkg/$(GOOS)_$(GOARCH) -lcgo -lgmp + +gmp.a: 6c.6 go.6 + gopack grc gmp.a 6c.6 go.6 + +# from pkg/runtime/Makefile: TODO(rsc): how to deal with this? +# Set SIZE to 32 or 64. +SIZE_386=32 +SIZE_amd64=64 +SIZE_arm=32 +SIZE=$(SIZE_$(GOARCH)) + +# Setup CFLAGS. Add -D_64BIT on 64-bit platforms (sorry). +CFLAGS_64=-D_64BIT +# TODO(kaib): fix register allocation to honor extern register so we +# can enable optimizations again. +CFLAGS_arm=-N +CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF $(CFLAGS_$(SIZE)) $(CFLAGS_$(GOARCH)) + +6c.6: 6c.c + 6c -FVw $(CFLAGS) -I$(GOROOT)/src/pkg/runtime 6c.c + +go.6: go.go + 6g go.go + +PKG=$(GOROOT)/pkg/$(GOOS)_$(GOARCH) + +install: $(PKG)/gmp.so $(PKG)/gmp.a + +$(PKG)/gmp.so: gmp.so + cp gmp.so $@ + +$(PKG)/gmp.a: gmp.a + cp gmp.a $@ + +clean: + rm -f *.6 *.o *.so *.a + diff --git a/usr/rsc/gmp/gcc.c b/usr/rsc/gmp/gcc.c new file mode 100644 index 0000000000..2e1c884e29 --- /dev/null +++ b/usr/rsc/gmp/gcc.c @@ -0,0 +1,54 @@ +// 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. + +#include +#include +#include + +typedef int32_t int32; +typedef uint64_t uint64; + +typedef struct Int Int; +struct Int +{ + mpz_t *mp; +}; + +void +gmp_newInt(void *v) +{ + struct { + uint64 x; + Int *z; + } *a = v; + + a->z->mp = malloc(sizeof *a->z->mp); + mpz_init_set_ui(*a->z->mp, a->x); +} + +void +gmp_addInt(void *v) +{ + struct { + Int *z; + Int *x; + Int *y; + Int *ret; + } *a = v; + + a->ret = a->z; + mpz_add(*a->z->mp, *a->x->mp, *a->y->mp); +} + +void +gmp_stringInt(void *v) +{ + struct { + Int *z; + char *p; + } *a = v; + + a->p = mpz_get_str(NULL, 10, *a->z->mp); +} + diff --git a/usr/rsc/gmp/go.go b/usr/rsc/gmp/go.go new file mode 100644 index 0000000000..68063087c9 --- /dev/null +++ b/usr/rsc/gmp/go.go @@ -0,0 +1,24 @@ +// 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. + +package gmp + +type Int struct { + hidden *byte +} + +func addInt(z, x, y *Int) *Int + +func (z *Int) Add(x, y *Int) *Int { + return addInt(z, x, y) +} + +func stringInt(z *Int) string + +func (z *Int) String() string { + return stringInt(z) +} + +func NewInt(n uint64) *Int + diff --git a/usr/rsc/gmp/main.go b/usr/rsc/gmp/main.go new file mode 100644 index 0000000000..0b25d25447 --- /dev/null +++ b/usr/rsc/gmp/main.go @@ -0,0 +1,28 @@ +// 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. + + +package main + +import big "gmp" +//import "big" +import "fmt" + +func Fib(n int) *big.Int { + a := big.NewInt(0); + b := big.NewInt(1); + + for i := 0; i < n; i++ { + a, b = b, a; + b.Add(a, b); + } + + return b; +} + +func main() { + for i := 0; i <= 100; i++ { + fmt.Println(5*i, Fib(5*i)); + } +}