LIBPFM(3)

πŸ“¦
version 4.14.1 Β· 2 versions
, in arch rolling, centos-stream 10, centos-stream 9, debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu questing, ubuntu resolute, ubuntu stonking

LIBPFM(3) β€” the Linux Programmer's Manual moment πŸ’–

okay bestie, sit down, hydrate, because we're about to talk about pfm_get_perf_event_encoding from the LIBPFM(3) manual. this one's giving "old faithful but make it deprecated" energy and i need you to be normal about it. 🫢


✨ NAME ✨

pfm_get_perf_event_encoding β€” the little function that encodes an event for the perf_event API. that's it. that's the whole job. she's a translator, she's a vibe. πŸ’…


✨ SYNOPSIS ✨

#include <perfmon/pfmlib_perf_event.h>

int pfm_get_perf_event_encoding(const char *str, int dfl_plm, struct perf_event_attr *attr, char **fstr, int *idx);

look at her. five arguments. main character behavior fr fr. 🌸


✨ DESCRIPTION ✨

so here's the tea β˜• β€” this function is the bestie of the perf_events Linux kernel API, which is the thing that gives you access to hardware performance counters, kernel software counters and tracepoints. iconic trio, no notes.

what she does: you hand her an event string in str plus a default privilege level mask in dfl_plm, and she fills out the relevant parts of the perf_events-specific data structure in attr. that's the whole flow. she's not doing extra. she's not doing less. 😌

🚨 deprecation check, bestie!! This function is deprecated. It is superseded by pfm_get_os_event_encoding() with the OS argument set to either PFM_OS_PERF_EVENT or PFM_OS_PERF_EVENT_EXT. Using this function provides extended support for perf_events. Certain perf_event configuration options are only available through this new interface. so like… she still works, but the new girl has the features. 😭

the glow-up, illustrated πŸ’«

The following examples illustrates the transition. so here's the before:

struct perf_event_attr attr;
int i, count = 0;
uint64_t *codes;

memset(&attr, 0, sizeof(attr));

ret = pfm_get_perf_event_encoding("RETIRED_INSTRUCTIONS", PFM_PLM3, &attrs, NULL, NULL);
if (ret != PFM_SUCCESS)
   err(1, "cannot get encoding %s", pfm_strerror(ret));

is equivalent to:

#include <perfmon/pfmlib_perf_event.h>
struct perf_event_attr attr;
pfm_perf_encode_arg_t arg;

memset(&arg, 0, sizeof(arg));
arg.size = sizeof(arg);
arg.attr = &attr;

ret = pfm_get_os_event_encoding("RETIRED_INSTRUCTIONS", PFM_PLM3, PFM_OS_PERF, &arg);
if (ret != PFM_SUCCESS)
   err(1, "cannot get encoding %s", pfm_strerror(ret));

see how the new one's got a whole arg situation going on? growth. evolution. she ate. πŸ”₯


privilege levels, aka the plm lore πŸ‘‘

The dfl_plm cannot be zero, though it may not necessarily be used by the event. Depending on the event, combination of the following privilege levels may be used:

  • PFM_PLM3 β€” Measure at privilege level 3. This usually corresponds to user level. On X86, it corresponds to privilege levels 3, 2, 1. Check the PMU specific man page to verify if this level is supported by your PMU model. πŸ‘€
  • PFM_PLM2 β€” Measure at privilege level 2. Check the PMU specific man page to verify if this level is supported by your PMU model.
  • PFM_PLM1 β€” Measure at privilege level 1. Check the PMU specific man page to verify if this level is supported by your PMU model.
  • PFM_PLM0 β€” Measure at privilege level 0. This usually corresponds to kernel level. Check the PMU specific man page to verify if this level is supported by your PMU model.
  • PFM_PLMH β€” Measure at hypervisor privilege level. This is used in conjunction with hardware virtualization. Check the PMU specific man page to verify if this level is supported by your PMU model.

the way every single one of these says "check the PMU specific man page"? she's literally telling you to go read more. respect. πŸ“š


fstr and idx shenanigans πŸŽ€

If fstr is not NULL, the function will make it point to the fully qualified event string β€” i.e., a string with the event name, all unit masks set, and the value of all modifiers. The library will allocate memory to store the event string, but it is the responsibility of the caller to eventually free that string using free().

πŸ’€ not the library handing you a pointer and dipping. you free it. you. with free(). don't forget or it's a leak, bestie, and leaks are not cute.

If idx is not NULL, it returns the corresponding unique event identifier. cute, right? a little bonus number. ✨


what she touches and what she leaves alone πŸ™ˆ

Only select fields are modified by the function, the others are untouched. The following fields in attr are modified:

  • type β€” The type of the event
  • config β€” The encoding of the event
  • exclude_user β€” Whether or not user level execution should be excluded from monitoring. The definition of user is PMU model specific.
  • exclude_kernel β€” Whether or not kernel level execution should be excluded from monitoring. The definition of kernel is PMU model specific.
  • exclude_hv β€” Whether or not hypervisor level execution should be excluded from monitoring. The definition of hypervisor is PMU model specific.

By default, if no privilege level modifier is specified in the event string, the library clears exclude_user, exclude_kernel and exclude_hv, resulting in the event being measured at all levels subject to hardware support. so like, everything everywhere all at once, hardware permitting. 🌈


one event at a time, but make it convenient πŸ’…

The function is able to work on only one event at a time. For convenience, it accepts event strings with commas. In that case, it will translate the first event up to the first comma. This is handy in case tools gets passed events as a comma-separated list.

so she reads up to the first comma and just… stops. she's not nosy. she's not reading your whole list. she's got one job. βœ‹


✨ RETURN ✨

The function returns in attr the perf_event encoding which corresponds to the event string. If idx is not NULL, then it will contain the unique event identifier upon successful return. The value PFM_SUCCESS is returned if successful, otherwise a negative error code is returned.

negative error code = not slay. check ERRORS below, bestie. 😭


✨ ERRORS ✨

  • PFM_ERR_TOOSMALL β€” The code argument is too small for the encoding.
  • PFM_ERR_INVAL β€” The attr argument is NULL.
  • PFM_ERR_NOMEM β€” Not enough memory.
  • PFM_ERR_NOTFOUND β€” Event not found.
  • PFM_ERR_ATTR β€” Invalid event attribute (unit mask or modifier)
  • PFM_ERR_ATTR_VAL β€” Invalid modifier value.
  • PFM_ERR_ATTR_SET β€” attribute already set, cannot be changed.
  • PFM_ERR_ATTR_UMASK β€” Missing unit mask.
  • PFM_ERR_ATTR_FEATCOMB β€” Unit masks or features cannot be combined into a single event.

✨ AUTHOR ✨

Stephane Eranian <eranian@gmail.com> 🫢 β€” thank you for your service, king.


✨ SEE ALSO ✨


okay that's the whole page, you're officially educated, i'm so proud of you, go forth and encode responsibly πŸ’–βœ¨πŸŽ€πŸ¦‹πŸŒΈπŸ’…

September, 2009 β€” LIBPFM(3) β€” the source/version and date of this little legend, signing off. bye bestie!! πŸ‘‘πŸŒˆβ­