in kernel/perf_event.c [878:917]
int csky_pmu_event_set_period(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
s64 left = local64_read(&hwc->period_left);
s64 period = hwc->sample_period;
int ret = 0;
if (unlikely(left <= -period)) {
left = period;
local64_set(&hwc->period_left, left);
hwc->last_period = period;
ret = 1;
}
if (unlikely(left <= 0)) {
left += period;
local64_set(&hwc->period_left, left);
hwc->last_period = period;
ret = 1;
}
if (left > (s64)csky_pmu.max_period)
left = csky_pmu.max_period;
/*
* The hw event starts counting from this event offset,
* mark it to be able to extract future "deltas":
*/
local64_set(&hwc->prev_count, (u64)(-left));
if (hw_raw_write_mapping[hwc->idx] != NULL)
hw_raw_write_mapping[hwc->idx]((u64)(-left) &
csky_pmu.max_period);
cpwcr(HPOFSR, ~BIT(hwc->idx) & cprcr(HPOFSR));
perf_event_update_userpage(event);
return ret;
}