Hi, Lukas -
Here's a more worked-out non-pmstore-proposal for automatic
activation of papi counters.
- as each client arrives to the pmda (papi_contextAttributeCallBack),
simply store its uid/gid credentials; drop the wildcard/trackers[]
bits from uid_gid_tuple; do not worry about getgrname() anything; do
not perform access control calculations at this time
- as each client leaves the pmda (papi_end_contextCallBack), drop its
ctxtab[] entry; do not change papi state at this time
- instead of a per-client trackers[], have a single global table to
represent the kernel papi-eventset state, containing rows:
- pmid
- papi eventcode
- a boolean enabled-flag
- the unique eventset-index for the eventcode within the eventset
- a long_long counter-base value (see below)
- time_t of last fetch of that
- a single kernel papi-eventset object, representing those papi events
whose enabled-flags are currently set, and a counter for how many are
currently in there
(in the near future, when per-process counters are built out,
generalize the above as appropriate)
- when receiving a fetch for the kernel papi pmns leaf:
- check ACL for this client; reject with EPERM if uid/gid != 0
- find corresponding entry in trackers[] table
- update its last_fetch tiemstamp
- if event is already enabled:
- PAPI_read() the eventset into a temporary long_long
array of suitable size
- find the slot# that corresponds to the pcp metric being
sought (the trackers[].eventset-index value)
- extract the counter value
- add it to the trackers[].counter_base value
- return the result as the metric counter value
- if the event was not already enabled:
- we need to update the eventset, but must counting first
- if this is the first event (eventset size = 0):
- create the eventset
- put it into multiplexing mode
- else this is not the first event:
- PAPI_stop() the eventset, collecting the then-values of
the counters into a temporary long_long array of suitable size
- copy all the counter values into the corresponding
trackers[].counter_base, so we don't forget in-progress values
- add the newly requested eventcode into the eventset, set its
enabled flag, compute its new eventset-index, clear its counter_base
- prepare to return an error upon failure
- PAPI_reset() (just to be clear that previous papi counter
values are lost when we restart)
- PAPI_start() the eventset -- even if the new event wasn't cool
- in the pmda main loop, periodically (suggested default 5 minutes) go
through the trackers[] list
- if any last-fetched value is too long ago, it's time to stop monitoring them
- call PAPI_stop on the eventset, collecting the then-values of the
counters into the trackers[].counter_base just as before
- clear the eventset completely
- add the surviving eventcodes back into the eventset, computing new correct
eventset-indexes as we go
- clear the dead eventcodes' trackers[] fields
- PAPI_reset() # redundantly, as before
- PAPI_start()
... and that should apprx. do it.
For bonus points, consider adding some control metrics:
- a setting for the counter-disuse-timeout
- a setting for immediate release (ie timeout=0 then cleanup then restore)
- a setting for activation of one or more counters (for old schoolers,
treat it identically to a fetch)
- FChE
|