205 lines
6.6 KiB
Go
205 lines
6.6 KiB
Go
//go:build linux && amd64
|
|
|
|
package intel_pmu
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
ia "github.com/intel/iaevents"
|
|
)
|
|
|
|
type placementMaker interface {
|
|
makeCorePlacements(cores []int, factory ia.PlacementFactory) ([]ia.PlacementProvider, error)
|
|
makeUncorePlacements(socket int, factory ia.PlacementFactory) ([]ia.PlacementProvider, error)
|
|
}
|
|
|
|
type iaPlacementMaker struct{}
|
|
|
|
func (iaPlacementMaker) makeCorePlacements(cores []int, factory ia.PlacementFactory) ([]ia.PlacementProvider, error) {
|
|
var err error
|
|
var corePlacements []ia.PlacementProvider
|
|
|
|
switch len(cores) {
|
|
case 0:
|
|
return nil, errors.New("no cores provided")
|
|
case 1:
|
|
corePlacements, err = ia.NewCorePlacements(factory, cores[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
default:
|
|
corePlacements, err = ia.NewCorePlacements(factory, cores[0], cores[1:]...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return corePlacements, nil
|
|
}
|
|
|
|
func (iaPlacementMaker) makeUncorePlacements(socket int, factory ia.PlacementFactory) ([]ia.PlacementProvider, error) {
|
|
return ia.NewUncoreAllPlacements(factory, socket)
|
|
}
|
|
|
|
type eventsActivator interface {
|
|
activateEvent(ia.Activator, ia.PlacementProvider, ia.Options) (*ia.ActiveEvent, error)
|
|
activateGroup(ia.PlacementProvider, []ia.CustomizableEvent) (*ia.ActiveEventGroup, error)
|
|
activateMulti(ia.MultiActivator, []ia.PlacementProvider, ia.Options) (*ia.ActiveMultiEvent, error)
|
|
}
|
|
|
|
type iaEventsActivator struct{}
|
|
|
|
func (iaEventsActivator) activateEvent(a ia.Activator, p ia.PlacementProvider, o ia.Options) (*ia.ActiveEvent, error) {
|
|
return a.Activate(p, ia.NewEventTargetProcess(-1, 0), o)
|
|
}
|
|
|
|
func (iaEventsActivator) activateGroup(p ia.PlacementProvider, e []ia.CustomizableEvent) (*ia.ActiveEventGroup, error) {
|
|
return ia.ActivateGroup(p, ia.NewEventTargetProcess(-1, 0), e)
|
|
}
|
|
|
|
func (iaEventsActivator) activateMulti(a ia.MultiActivator, p []ia.PlacementProvider, o ia.Options) (*ia.ActiveMultiEvent, error) {
|
|
return a.ActivateMulti(p, ia.NewEventTargetProcess(-1, 0), o)
|
|
}
|
|
|
|
type entitiesActivator interface {
|
|
activateEntities(coreEntities []*coreEventEntity, uncoreEntities []*uncoreEventEntity) error
|
|
}
|
|
|
|
type iaEntitiesActivator struct {
|
|
placementMaker placementMaker
|
|
perfActivator eventsActivator
|
|
}
|
|
|
|
func (ea *iaEntitiesActivator) activateEntities(coreEntities []*coreEventEntity, uncoreEntities []*uncoreEventEntity) error {
|
|
for _, coreEventsEntity := range coreEntities {
|
|
err := ea.activateCoreEvents(coreEventsEntity)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to activate core events %q: %w", coreEventsEntity.EventsTag, err)
|
|
}
|
|
}
|
|
for _, uncoreEventsEntity := range uncoreEntities {
|
|
err := ea.activateUncoreEvents(uncoreEventsEntity)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to activate uncore events %q: %w", uncoreEventsEntity.EventsTag, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ea *iaEntitiesActivator) activateCoreEvents(entity *coreEventEntity) error {
|
|
if entity == nil {
|
|
return errors.New("core events entity is nil")
|
|
}
|
|
if ea.placementMaker == nil {
|
|
return errors.New("placement maker is nil")
|
|
}
|
|
if entity.PerfGroup {
|
|
err := ea.activateCoreEventsGroup(entity)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to activate core events group: %w", err)
|
|
}
|
|
} else {
|
|
for _, event := range entity.parsedEvents {
|
|
if event == nil {
|
|
return errors.New("core parsed event is nil")
|
|
}
|
|
placements, err := ea.placementMaker.makeCorePlacements(entity.parsedCores, event.custom.Event)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create core placements for event %q: %w", event.name, err)
|
|
}
|
|
activeEvents, err := ea.activateEventForPlacements(event, placements)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to activate core event %q: %w", event.name, err)
|
|
}
|
|
entity.activeEvents = append(entity.activeEvents, activeEvents...)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ea *iaEntitiesActivator) activateUncoreEvents(entity *uncoreEventEntity) error {
|
|
if entity == nil {
|
|
return errors.New("uncore events entity is nil")
|
|
}
|
|
if ea.perfActivator == nil || ea.placementMaker == nil {
|
|
return errors.New("events activator or placement maker is nil")
|
|
}
|
|
for _, event := range entity.parsedEvents {
|
|
if event == nil {
|
|
return errors.New("uncore parsed event is nil")
|
|
}
|
|
perfEvent := event.custom.Event
|
|
if perfEvent == nil {
|
|
return fmt.Errorf("perf event of %q event is nil", event.name)
|
|
}
|
|
options := event.custom.Options
|
|
|
|
for _, socket := range entity.parsedSockets {
|
|
placements, err := ea.placementMaker.makeUncorePlacements(socket, perfEvent)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create uncore placements for event %q: %w", event.name, err)
|
|
}
|
|
activeMultiEvent, err := ea.perfActivator.activateMulti(perfEvent, placements, options)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to activate multi event %q: %w", event.name, err)
|
|
}
|
|
events := activeMultiEvent.Events()
|
|
entity.activeMultiEvents = append(entity.activeMultiEvents, multiEvent{events, perfEvent, socket})
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ea *iaEntitiesActivator) activateCoreEventsGroup(entity *coreEventEntity) error {
|
|
if ea.perfActivator == nil || ea.placementMaker == nil {
|
|
return errors.New("missing perf activator or placement maker")
|
|
}
|
|
if entity == nil || len(entity.parsedEvents) < 1 {
|
|
return errors.New("missing parsed events")
|
|
}
|
|
|
|
events := make([]ia.CustomizableEvent, 0, len(entity.parsedEvents))
|
|
for _, event := range entity.parsedEvents {
|
|
if event == nil {
|
|
return errors.New("core event is nil")
|
|
}
|
|
events = append(events, event.custom)
|
|
}
|
|
leader := entity.parsedEvents[0].custom
|
|
|
|
placements, err := ea.placementMaker.makeCorePlacements(entity.parsedCores, leader.Event)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to make core placements: %w", err)
|
|
}
|
|
|
|
for _, plc := range placements {
|
|
activeGroup, err := ea.perfActivator.activateGroup(plc, events)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
entity.activeEvents = append(entity.activeEvents, activeGroup.Events()...)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ea *iaEntitiesActivator) activateEventForPlacements(event *eventWithQuals, placements []ia.PlacementProvider) ([]*ia.ActiveEvent, error) {
|
|
if event == nil {
|
|
return nil, errors.New("core event is nil")
|
|
}
|
|
if ea.perfActivator == nil {
|
|
return nil, errors.New("missing perf activator")
|
|
}
|
|
|
|
activeEvents := make([]*ia.ActiveEvent, 0, len(placements))
|
|
for _, placement := range placements {
|
|
perfEvent := event.custom.Event
|
|
options := event.custom.Options
|
|
|
|
activeEvent, err := ea.perfActivator.activateEvent(perfEvent, placement, options)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to activate event %q: %w", event.name, err)
|
|
}
|
|
activeEvents = append(activeEvents, activeEvent)
|
|
}
|
|
return activeEvents, nil
|
|
}
|