mirror of
https://github.com/golang/go
synced 2024-11-25 21:47:59 -07:00
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
This commit is contained in:
parent
429157848f
commit
75a38963ca
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
60
usr/rsc/gmp/6c.c
Normal file
60
usr/rsc/gmp/6c.c
Normal file
@ -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);
|
||||
}
|
||||
|
52
usr/rsc/gmp/Makefile
Normal file
52
usr/rsc/gmp/Makefile
Normal file
@ -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
|
||||
|
54
usr/rsc/gmp/gcc.c
Normal file
54
usr/rsc/gmp/gcc.c
Normal file
@ -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);
|
||||
}
|
||||
|
24
usr/rsc/gmp/go.go
Normal file
24
usr/rsc/gmp/go.go
Normal file
@ -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
|
||||
|
28
usr/rsc/gmp/main.go
Normal file
28
usr/rsc/gmp/main.go
Normal file
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user