Skip to content

Commit

Permalink
add OpenPerfEvent API so that tables can be configured to catch perf …
Browse files Browse the repository at this point in the history
…event counters in bpf programs
  • Loading branch information
rootfs committed May 1, 2023
1 parent 16120a1 commit 20175af
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions bcc/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,58 @@ func (bpf *Module) AttachPerfEvent(evType, evConfig int, samplePeriod int, sampl
return nil
}

// OpenPerfEvent attaches perf events, describe by parameters `typ` and `config`, to a Table.
// The described perf event counters can be fetched in `BPF_PERF_ARRAY` that the Table is associated with.
// a typical invocation process is as the following
// in BPF program:
// BPF_PERF_ARRAY(cpu_cycles, NUM_CPUS);
// ...
// u64 val = cpu_cycles.perf_read(CUR_CPU_IDENTIFIER);
// In go program:
// evType := unix.PERF_TYPE_HARDWARE
// evConfig := unix.PERF_COUNT_HW_CPU_CYCLES
// t := bpf.NewTable(m.TableId("cpu_cycles"), m)
// if t != nil { return bpf.OpenPerfEvent(t, evType, evConfig) }
func (bpf *Module) OpenPerfEvent(table *bpf.Table, typ, config int) error {
// the perf key is different from those used by `AttachPerfEvent`
perfKey := fmt.Sprintf("perf:%d:%d", typ, config)
if _, ok := bpf.perfEvents[perfKey]; ok {
return nil
}

cpus, err := cpuonline.Get()
if err != nil {
return fmt.Errorf("failed to determine online cpus: %v", err)
}
keySize := table.Config()["key_size"].(uint64)
leafSize := table.Config()["leaf_size"].(uint64)

if keySize != 4 || leafSize != 4 {
return fmt.Errorf("passed table has wrong size")
}

res := []int{}

for _, i := range cpus {
fd, err := C.bpf_open_perf_event(C.uint(typ), C.ulong(config), C.int(-1), C.int(i))
if fd < 0 {
return fmt.Errorf("failed to open bpf perf event: %v", err)
}
key := make([]byte, keySize)
leaf := make([]byte, leafSize)
byteOrder.PutUint32(key, uint32(i))
byteOrder.PutUint32(leaf, uint32(fd))
keyP := unsafe.Pointer(&key[0])
leafP := unsafe.Pointer(&leaf[0])
table.SetP(keyP, leafP)
res = append(res, int(fd))
}

bpf.perfEvents[perfKey] = res

return nil
}

// AttachUprobe attaches a uprobe fd to the symbol in the library or binary 'name'
// The 'name' argument can be given as either a full library path (/usr/lib/..),
// a library without the lib prefix, or as a binary with full path (/bin/bash)
Expand Down

0 comments on commit 20175af

Please sign in to comment.