static int arc_pmu_event_set_period()

in kernel/perf_event.c [405:444]


static int arc_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 idx = hwc->idx;
	int overflow = 0;
	u64 value;

	if (unlikely(left <= -period)) {
		/* left underflowed by more than period. */
		left = period;
		local64_set(&hwc->period_left, left);
		hwc->last_period = period;
		overflow = 1;
	} else if (unlikely(left <= 0)) {
		/* left underflowed by less than period. */
		left += period;
		local64_set(&hwc->period_left, left);
		hwc->last_period = period;
		overflow = 1;
	}

	if (left > arc_pmu->max_period)
		left = arc_pmu->max_period;

	value = arc_pmu->max_period - left;
	local64_set(&hwc->prev_count, value);

	/* Select counter */
	write_aux_reg(ARC_REG_PCT_INDEX, idx);

	/* Write value */
	write_aux_reg(ARC_REG_PCT_COUNTL, lower_32_bits(value));
	write_aux_reg(ARC_REG_PCT_COUNTH, upper_32_bits(value));

	perf_event_update_userpage(event);

	return overflow;
}