+static int pmu_validate_cgroups(core_group_t *cgroups, size_t len,
+ int max_cores) {
+ /* i - group index, j - core index */
+ for (size_t i = 0; i < len; i++) {
+ for (size_t j = 0; j < cgroups[i].num_cores; j++) {
+ int core = (int)cgroups[i].cores[j];
+
+ /* Core index cannot exceed number of cores in system,
+ note that max_cores include both online and offline CPUs. */
+ if (core >= max_cores) {
+ ERROR(PMU_PLUGIN ": Core %d is not valid, max core index: %d.", core,
+ max_cores - 1);
+ return -1;
+ }
+ }
+ /* Check if cores are set in remaining groups */
+ for (size_t k = i + 1; k < len; k++)
+ if (config_cores_cmp_cgroups(&cgroups[i], &cgroups[k]) != 0) {
+ ERROR(PMU_PLUGIN ": Same cores cannot be set in different groups.");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int pmu_config_hw_events(oconfig_item_t *ci) {
+
+ if (strcasecmp("HardwareEvents", ci->key) != 0) {
+ return -EINVAL;
+ }
+
+ if (g_ctx.hw_events) {
+ ERROR(PMU_PLUGIN ": Duplicate config for HardwareEvents.");
+ return -EINVAL;
+ }
+
+ g_ctx.hw_events = calloc(ci->values_num, sizeof(*g_ctx.hw_events));
+ if (g_ctx.hw_events == NULL) {
+ ERROR(PMU_PLUGIN ": Failed to allocate hw events.");
+ return -ENOMEM;
+ }
+
+ for (int i = 0; i < ci->values_num; i++) {
+ if (ci->values[i].type != OCONFIG_TYPE_STRING) {
+ WARNING(PMU_PLUGIN ": The %s option requires string arguments.", ci->key);
+ continue;
+ }
+
+ g_ctx.hw_events[g_ctx.hw_events_count] = strdup(ci->values[i].value.string);
+ if (g_ctx.hw_events[g_ctx.hw_events_count] == NULL) {
+ ERROR(PMU_PLUGIN ": Failed to allocate hw events entry.");
+ return -ENOMEM;
+ }
+
+ g_ctx.hw_events_count++;
+ }
+
+ return 0;
+}
+