]> Cypherpunks repositories - gostls13.git/commitdiff
cgocall bug fix.
authorRuss Cox <rsc@golang.org>
Tue, 25 Aug 2009 04:16:15 +0000 (21:16 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 25 Aug 2009 04:16:15 +0000 (21:16 -0700)
better FFI demo: compute fibonacci numbers using FFI'ed libgmp.

R=r
DELTA=281  (255 added, 19 deleted, 7 changed)
OCL=33815
CL=33820

src/libcgo/cgocall.c
usr/rsc/gmp/6c.c [new file with mode: 0644]
usr/rsc/gmp/Makefile [new file with mode: 0644]
usr/rsc/gmp/gcc.c [new file with mode: 0644]
usr/rsc/gmp/go.go [new file with mode: 0644]
usr/rsc/gmp/main.go [new file with mode: 0644]

index c089f1d5d5c5fa2d6cf142556b91b9e359c227c5..d501a38efd5bfe0ee9325b9c90ff273abef9483c 100644 (file)
@@ -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 (file)
index 0000000..10d48ad
--- /dev/null
@@ -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 (file)
index 0000000..93053d0
--- /dev/null
@@ -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 (file)
index 0000000..2e1c884
--- /dev/null
@@ -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 <stdint.h>
+#include <gmp.h>
+#include <string.h>
+
+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 (file)
index 0000000..6806308
--- /dev/null
@@ -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 (file)
index 0000000..0b25d25
--- /dev/null
@@ -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));
+       }
+}