Skip to content

Commit 20175af

Browse files
committed
add OpenPerfEvent API so that tables can be configured to catch perf event counters in bpf programs
1 parent 16120a1 commit 20175af

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

bcc/module.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,58 @@ func (bpf *Module) AttachPerfEvent(evType, evConfig int, samplePeriod int, sampl
393393
return nil
394394
}
395395

396+
// OpenPerfEvent attaches perf events, describe by parameters `typ` and `config`, to a Table.
397+
// The described perf event counters can be fetched in `BPF_PERF_ARRAY` that the Table is associated with.
398+
// a typical invocation process is as the following
399+
// in BPF program:
400+
// BPF_PERF_ARRAY(cpu_cycles, NUM_CPUS);
401+
// ...
402+
// u64 val = cpu_cycles.perf_read(CUR_CPU_IDENTIFIER);
403+
// In go program:
404+
// evType := unix.PERF_TYPE_HARDWARE
405+
// evConfig := unix.PERF_COUNT_HW_CPU_CYCLES
406+
// t := bpf.NewTable(m.TableId("cpu_cycles"), m)
407+
// if t != nil { return bpf.OpenPerfEvent(t, evType, evConfig) }
408+
func (bpf *Module) OpenPerfEvent(table *bpf.Table, typ, config int) error {
409+
// the perf key is different from those used by `AttachPerfEvent`
410+
perfKey := fmt.Sprintf("perf:%d:%d", typ, config)
411+
if _, ok := bpf.perfEvents[perfKey]; ok {
412+
return nil
413+
}
414+
415+
cpus, err := cpuonline.Get()
416+
if err != nil {
417+
return fmt.Errorf("failed to determine online cpus: %v", err)
418+
}
419+
keySize := table.Config()["key_size"].(uint64)
420+
leafSize := table.Config()["leaf_size"].(uint64)
421+
422+
if keySize != 4 || leafSize != 4 {
423+
return fmt.Errorf("passed table has wrong size")
424+
}
425+
426+
res := []int{}
427+
428+
for _, i := range cpus {
429+
fd, err := C.bpf_open_perf_event(C.uint(typ), C.ulong(config), C.int(-1), C.int(i))
430+
if fd < 0 {
431+
return fmt.Errorf("failed to open bpf perf event: %v", err)
432+
}
433+
key := make([]byte, keySize)
434+
leaf := make([]byte, leafSize)
435+
byteOrder.PutUint32(key, uint32(i))
436+
byteOrder.PutUint32(leaf, uint32(fd))
437+
keyP := unsafe.Pointer(&key[0])
438+
leafP := unsafe.Pointer(&leaf[0])
439+
table.SetP(keyP, leafP)
440+
res = append(res, int(fd))
441+
}
442+
443+
bpf.perfEvents[perfKey] = res
444+
445+
return nil
446+
}
447+
396448
// AttachUprobe attaches a uprobe fd to the symbol in the library or binary 'name'
397449
// The 'name' argument can be given as either a full library path (/usr/lib/..),
398450
// a library without the lib prefix, or as a binary with full path (/bin/bash)

0 commit comments

Comments
 (0)