Skip to content

Instantly share code, notes, and snippets.

@ecin
Created August 31, 2012 17:34
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save ecin/3556241 to your computer and use it in GitHub Desktop.
Save ecin/3556241 to your computer and use it in GitHub Desktop.
Dtrace probes in your Golang code
package main
/*
Ping vs Pong: A Gladiatorial Match
Two goroutines enter, only one leaves...
*/
/*
#cgo LDFLAGS: -lprobes -L/usr/local/lib
#include "probes.h"
*/
import "C"
import (
"time"
"math/rand"
)
func ping(c chan int, q chan int) {
for ;; {
// Prepare a swing
time.Sleep(time.Duration(rand.Intn(5)) * time.Second)
n := <- c
n += 1
if n == 10 {
q <- 0
}
c <- n
// Dtrace spectators: roar for Ping!
C.Ping(C.int(n))
}
}
func pong(c chan int, q chan int) {
for ;; {
// Charge an attack
time.Sleep(time.Duration(rand.Intn(5)) * time.Second)
n := <- c
n -= 1
if n == 0 {
q <- 1
}
c <- n
// Dtrace spectators: cheer for Pong!
C.Pong(C.int(n))
}
}
func main() {
c := make(chan int, 2)
q := make(chan int)
// Ping and Pong enter the arena
go ping(c, q)
go pong(c, q)
// The match starts!
c <- 5
// Wait for victor signal
winner := <- q
if winner == 0 {
println("After a long and arduous battle, Pong falls to its knees, its body a weary mess. Ping wins!")
} else {
println("Overcome by one too many wounds, Ping rushes to the ground. Pong wins!")
}
}
/*
Compile probes.c as a shared library
In Mac OS X (http://www.finkproject.org/doc/porting/shared.php#build-lib):
cc -fno-common -c probes.c
cc -dynamiclib -install_name /usr/local/lib/libprobes.dylib -o libprobes.dylib probes.o
cp libprobes.dylib /usr/local/lib/
*/
#include "probes.h"
void Ping(int n) {
GOLANG_PING(n);
}
int Ping_enabled() {
return GOLANG_PING_ENABLED();
}
void Pong(int n) {
GOLANG_PONG(n);
}
int Pong_enabled() {
return GOLANG_PONG_ENABLED();
}
/*
Generate probes.h header file with:
dtrace -o probes.h -h -s probes.d
*/
provider golang {
probe ping(int);
probe pong(int);
};
/* Header file generated by dtrace */
/* ... */
/* probes.c functions */
void Ping(int);
int Ping_enabled();
void Pong(int);
int Pong_enabled();
golang*::Ping:
{
printf("Ping hits, counter goes up to #%d!", arg0);
}
golang*::Pong:
{
printf("Pong connects, counter goes down to #%d!", arg0);
}
@ecin
Copy link
Author

ecin commented Sep 2, 2012

Demo of static Dtrace probes in Golang. Run with go run goarena.go, spectate with sudo dtrace -s spectator.d.

I failed at making Golang's cgo work nicely with a static library, which is why probes.c needs to be compiled as a shared library. Otherwise, dtrace's probe.h file could have been used directly.

Golang bindings for Chris Andrew's libusdt would probably allow more user-friendly dtrace probes in similar programs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment