/** * @brief Function to set the descriptions and cores for each core group * * Takes a string containing individual cores and groups of cores and * breaks it into substrings which are used to set core group values * * @param s string containing cores to be divided into substrings * @param tab table of core groups to set values in * @param max maximum number of core groups allowed * * @return Number of core groups set up * @retval -1 on error */ static int strtocgrps(char *s, struct core_group *tab, const unsigned max) { unsigned i, n, index = 0; uint64_t cbuf[PQOS_MAX_CORES]; char *non_grp = NULL; ASSERT(tab != NULL); ASSERT(max > 0); if (s == NULL) return index; while ((non_grp = strsep(&s, "[")) != NULL) { int ret; /** * If group contains single core */ if ((strlen(non_grp)) > 0) { n = strlisttotab(non_grp, cbuf, (max-index)); if ((index+n) > max) return -1; /* set core group info */ for (i = 0; i < n; i++) { char *desc = uinttostr((unsigned)cbuf[i]); ret = set_cgrp(&tab[index], desc, &cbuf[i], 1); if (ret < 0) return -1; index++; } } /** * If group contains multiple cores */ char *grp = strsep(&s, "]"); if (grp != NULL) { char *desc = NULL; selfn_strdup(&desc, grp); n = strlisttotab(grp, cbuf, (max-index)); if (index+n > max) { free(desc); return -1; } /* set core group info */ ret = set_cgrp(&tab[index], desc, cbuf, n); if (ret < 0) { free(desc); return -1; } index++; } } return index; }
/** * @brief Stores the process id's given in a table for future use * * @param str string of process id's */ static void sel_store_process_id(char *str) { uint64_t processes[PQOS_MAX_PIDS]; unsigned i = 0, n = 0; enum pqos_mon_event evt = 0; parse_event(str, &evt); n = strlisttotab(strchr(str, ':') + 1, processes, DIM(processes)); if (n == 0) parse_error(str, "No process id selected for monitoring"); if (n >= DIM(sel_monitor_pid_tab)) parse_error(str, "too many processes selected " "for monitoring"); /** * For each process: * - if it's already there in the sel_monitor_pid_tab * - update the entry * - else - add it to the sel_monitor_pid_tab */ for (i = 0; i < n; i++) { int j, found = 0; for (j = 0; j < sel_process_num && j < (int) DIM(sel_monitor_pid_tab); j++) { if (sel_monitor_pid_tab[j].pid == (pid_t)processes[i]) { sel_monitor_pid_tab[j].events |= evt; found = 1; break; } } if (!found && sel_process_num < (int) DIM(sel_monitor_pid_tab)) { struct pid_group *pg = &sel_monitor_pid_tab[sel_process_num]; pg->pid = (pid_t)processes[i]; pg->events = evt; pg->pgrp = malloc(sizeof(*pg->pgrp)); if (pg->pgrp == NULL) { printf("Error with memory allocation"); exit(EXIT_FAILURE); } ++sel_process_num; } } }
/** * @brief Verifies and translates allocation association config string into * internal configuration. * * @param str string passed to -a command line option */ static void parse_allocation_assoc(char *str) { uint64_t cores[PQOS_MAX_CORES]; unsigned i = 0, n = 0, cos = 0; char *p = NULL; if (strncasecmp(str, "llc:", 4) != 0) parse_error(str, "Unrecognized allocation type"); str += strlen("llc:"); p = strchr(str, '='); if (p == NULL) parse_error(str, "Invalid allocation class of service " "association format"); *p = '\0'; cos = (unsigned) strtouint64(str); n = strlisttotab(p+1, cores, DIM(cores)); if (n == 0) return; if (sel_cat_assoc_num <= 0) { for (i = 0; i < n; i++) { if (i >= DIM(sel_cat_assoc_tab)) parse_error(str, "too many cores selected for " "allocation association"); sel_cat_assoc_tab[i].core = (unsigned) cores[i]; sel_cat_assoc_tab[i].class_id = cos; } sel_cat_assoc_num = (int) n; return; } for (i = 0; i < n; i++) { int j; for (j = 0; j < sel_cat_assoc_num; j++) if (sel_cat_assoc_tab[j].core == (unsigned) cores[i]) break; if (j < sel_cat_assoc_num) { /** * this core is already on the list * - update COS but warn about it */ printf("warn: updating COS for core %u from %u to %u\n", (unsigned) cores[i], sel_cat_assoc_tab[j].class_id, cos); sel_cat_assoc_tab[j].class_id = cos; } else { /** * New core is selected - extend the list */ unsigned k = (unsigned) sel_cat_assoc_num; if (k >= DIM(sel_cat_assoc_tab)) parse_error(str, "too many cores selected for " "allocation association"); sel_cat_assoc_tab[k].core = (unsigned) cores[i]; sel_cat_assoc_tab[k].class_id = cos; sel_cat_assoc_num++; } } }
/** * @brief Verifies and translates definition of allocation class of service * from text string into internal configuration. * * @param str string passed to -e command line option */ static void parse_allocation_class(char *str) { char *s, *q, *p = NULL; char *saveptr = NULL; uint64_t *sp = NULL; uint64_t sockets[PQOS_MAX_SOCKETS]; unsigned i, n = 1; enum sel_cat_type type; s = strdup(str); if (s == NULL) s = str; p = strchr(str, ':'); if (p == NULL) parse_error(str, "Unrecognized allocation format"); /** * Set up selected sockets table */ q = strchr(str, '@'); if (q != NULL) { /** * Socket ID's selected - set up sockets table */ *p = '\0'; *q = '\0'; n = strlisttotab(++q, sockets, DIM(sockets)); if (n == 0) parse_error(s, "No socket ID specified"); /** * Check selected sockets are within range */ for (i = 0; i < n; i++) if (sockets[i] >= PQOS_MAX_SOCKETS) parse_error(s, "Socket ID out of range"); sp = sockets; } else *p = '\0'; /** * Determine selected CAT type (L3/L2) */ if (strcasecmp(str, "llc") == 0) type = L3CA; else if (strcasecmp(str, "l2") == 0) type = L2CA; else parse_error(s, "Unrecognized allocation type"); /** * Parse COS masks and apply to selected sockets */ for (++p; ; p = NULL) { char *token = NULL; token = strtok_r(p, ",", &saveptr); if (token == NULL) break; parse_allocation_cos(token, sp, n, type); } free(s); }