diff --git a/perf/collector_libpfm.go b/perf/collector_libpfm.go index 5637f7af4f..cbc646ba10 100644 --- a/perf/collector_libpfm.go +++ b/perf/collector_libpfm.go @@ -21,6 +21,7 @@ package perf // #cgo LDFLAGS: -lpfm // #include // #include +// #include import "C" import ( @@ -231,8 +232,18 @@ func (c *collector) setup() error { return nil } -func readPerfEventAttr(name string) (*unix.PerfEventAttr, error) { +func readPerfEventAttr(name string, pfmGetOsEventEncoding func(string, unsafe.Pointer) error) (*unix.PerfEventAttr, error) { perfEventAttrMemory := C.malloc(C.ulong(unsafe.Sizeof(unix.PerfEventAttr{}))) + // Fill memory with 0 values. + C.memset(perfEventAttrMemory, 0, C.ulong(unsafe.Sizeof(unix.PerfEventAttr{}))) + err := pfmGetOsEventEncoding(name, unsafe.Pointer(perfEventAttrMemory)) + if err != nil { + return nil, err + } + return (*unix.PerfEventAttr)(perfEventAttrMemory), nil +} + +func pfmGetOsEventEncoding(name string, perfEventAttrMemory unsafe.Pointer) error { event := pfmPerfEncodeArgT{} fstr := C.CString("") event.fstr = unsafe.Pointer(fstr) @@ -241,10 +252,9 @@ func readPerfEventAttr(name string) (*unix.PerfEventAttr, error) { cSafeName := C.CString(name) pErr := C.pfm_get_os_event_encoding(cSafeName, C.PFM_PLM0|C.PFM_PLM3, C.PFM_OS_PERF_EVENT, unsafe.Pointer(&event)) if pErr != C.PFM_SUCCESS { - return nil, fmt.Errorf("unable to transform event name %s to perf_event_attr: %d", name, int(pErr)) + return fmt.Errorf("unable to transform event name %s to perf_event_attr: %d", name, int(pErr)) } - - return (*unix.PerfEventAttr)(perfEventAttrMemory), nil + return nil } type eventInfo struct { @@ -408,7 +418,7 @@ func (c *collector) createConfigFromRawEvent(event *CustomEvent) *unix.PerfEvent func (c *collector) createConfigFromEvent(event Event) (*unix.PerfEventAttr, error) { klog.V(5).Infof("Setting up perf event %s", string(event)) - config, err := readPerfEventAttr(string(event)) + config, err := readPerfEventAttr(string(event), pfmGetOsEventEncoding) if err != nil { C.free((unsafe.Pointer)(config)) return nil, err diff --git a/perf/collector_libpfm_test.go b/perf/collector_libpfm_test.go index 4bd96880c7..7e484c538e 100644 --- a/perf/collector_libpfm_test.go +++ b/perf/collector_libpfm_test.go @@ -21,6 +21,9 @@ import ( "bytes" "encoding/binary" "testing" + "unsafe" + + "golang.org/x/sys/unix" "github.com/stretchr/testify/assert" @@ -387,3 +390,42 @@ func TestReadPerfStat(t *testing.T) { }) } } + +func TestReadPerfEventAttr(t *testing.T) { + var testCases = []struct { + expected *unix.PerfEventAttr + pfmMockedFunc func(string, unsafe.Pointer) error + }{ + { + &unix.PerfEventAttr{ + Type: 0, + Size: 0, + Config: 0, + Sample: 0, + Sample_type: 0, + Read_format: 0, + Bits: 0, + Wakeup: 0, + Bp_type: 0, + Ext1: 0, + Ext2: 0, + Branch_sample_type: 0, + Sample_regs_user: 0, + Sample_stack_user: 0, + Clockid: 0, + Sample_regs_intr: 0, + Aux_watermark: 0, + Sample_max_stack: 0, + }, + func(s string, pointer unsafe.Pointer) error { + return nil + }, + }, + } + + for _, test := range testCases { + got, err := readPerfEventAttr("event_name", test.pfmMockedFunc) + assert.NoError(t, err) + assert.Equal(t, test.expected, got) + } +} diff --git a/perf/uncore_libpfm.go b/perf/uncore_libpfm.go index d32dedfb41..fdd35a34b6 100644 --- a/perf/uncore_libpfm.go +++ b/perf/uncore_libpfm.go @@ -365,7 +365,7 @@ func (c *uncoreCollector) setupEvent(name string, pmus uncorePMUs, groupIndex in klog.V(5).Infof("Setting up uncore perf event %s", name) - config, err := readPerfEventAttr(name) + config, err := readPerfEventAttr(name, pfmGetOsEventEncoding) if err != nil { C.free((unsafe.Pointer)(config)) return err