LIBPFM(3)

✨ NAME ✨

pfm_get_event_encoding β€” get raw event encoding


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <perfmon/pfmlib.h>

int pfm_get_event_encoding(const char *str,int dfl_plm, char **fstr, int *idx, uint64_t *code, int *count);

πŸ’– DESCRIPTION πŸ’–

okay bestie, so this little function is your girl for turning an event string into its raw event encoding. You hand it str and it hands you back the encoding, periodt.

Important vibe check tho: one event per call. That's it. So str can hold exactly one symbolic event name β€” no sneaking a second one in there. It can contain unit masks and modifiers though, so dress it up however you like πŸŽ€. The default privilege level mask goes in dfl_plm, and whether it actually gets used depends on the event, so don't @ it.

⚠️ This function is DEPRECATED. It's been superseded by pfm_get_os_event_encoding(), where you set the OS to PFM_OS_NONE. Encoding gets retrieved through the pfm_pmu_encode_arg_t structure. We love a glow-up πŸ’…

Here's the transition, so you can see the before and after. This:

int i, count = 0;
uint64_t *codes;

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

for(i=0; i < count; i++)
   printf("count[%d]=0x%"PRIx64"\n", i, codes[i]);

is equivalent to:

pfm_pmu_encode_arg_t arg;
int i;

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

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

for(i=0; i < arg.count; i++)
   printf("count[%d]=0x%"PRIx64"\n", i, arg.codes[i]);

free(arg.codes);

See? Same energy, new outfit ✨

Now the tea on the encoding itself: it may take several 64-bit integers. The function can use the array you pass in code if the number of entries you passed in count is big enough. But here's the thing β€” if both *codes is NULL and count is 0, the function allocates the memory it needs to store the encoding all by itself, and it is up to you, the caller to eventually free that memory. No ghosting your mallocs, bestie 🫢

The number of 64-bit entries in codes gets reflected in *count upon return, regardless of whether codes was allocated for you or used as-is. And if that number is greater than one, then the order in which each component comes back is PMU-model specific β€” so go read the PMU specific man page, iykyk.

The "raw encoding" means the encoding as mandated by the underlying PMU model. Lowkey it may not be directly suitable to pass to a kernel API 😭, so you might want to use API-specific library calls to make sure the correct encoding is what actually gets passed. Slay responsibly.

If fstr is not NULL, it will point to the fully qualified event string upon successful return. That string contains the event name, any umask set, and the value of all the modifiers. Basically it reflects what the encoding will actually measure β€” receipts, fr fr. The function allocates the memory for that string, so the caller must eventually free it too.

Here's an example of how this function could be used:

#include <inttypes.h>
#include <err.h>
#include <perfmon/pfmlib.h>
int main(int argc, char **argv)
{
   uint64_t *codes 0;
   int count = 0;
   int ret;

   ret = pfm_initialize();
   if (ret != PFMLIB_SUCCESS)
      err(1", cannot initialize library %s", pfm_strerror(ret));

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

   for(i=0; i < count; i++)
      printf("count[%d]=0x%"PRIx64"\n", i, codes[i]);

   free(codes);
   return 0;
}

🌈 RETURN 🌈

The function returns the encoding of the event in *codes, and the number of 64-bit integers needed to support that encoding in *count. Upon success, PFM_SUCCESS is returned β€” otherwise you get a specific error code back, and it's giving 😭


πŸ’€ ERRORS πŸ’€

  • PFM_ERR_TOOSMALL β€” the code argument is too small for the encoding. Not enough room, bestie, she's overflowing πŸ™ˆ
  • PFM_ERR_INVAL β€” the code or count argument is NULL, or str contains more than one symbolic event. One event per call, I said what I said πŸ’…
  • PFM_ERR_NOMEM β€” not enough memory. The allocation said no βœ‹
  • PFM_ERR_NOTFOUND β€” event not found. She's not in the building πŸ‘‘
  • 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. Locked in, no take-backs πŸ”’
  • PFM_ERR_ATTR_UMASK β€” missing unit mask
  • PFM_ERR_ATTR_FEATCOMB β€” unit masks or features cannot be combined into a single event. These two are not compatible, and that's final πŸ’€

πŸŽ€ AUTHOR πŸŽ€

Stephane Eranian <eranian@gmail.com>


🌸 SEE ALSO 🌸

pfm_get_os_event_encoding(3)


and that's the whole page, babe β€” this one's from the Linux Programmer's Manual, LIBPFM(3), dated September, 2009 πŸ¦‹ thanks for reading, ily, go free your memory πŸ’–

πŸ“¦ where this page comes from