/** * @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; }
int monitor_setup(const struct pqos_cpuinfo *cpu_info, const struct pqos_capability const *cap_mon) { unsigned i; int ret; enum pqos_mon_event all_core_evts = 0, all_pid_evts = 0; const enum pqos_mon_event evt_all = (enum pqos_mon_event)PQOS_MON_EVENT_ALL; ASSERT(sel_monitor_num >= 0); ASSERT(sel_process_num >= 0); /** * Check output file type */ if (sel_output_type == NULL) sel_output_type = strdup("text"); if (sel_output_type == NULL) { printf("Memory allocation error!\n"); return -1; } if (strcasecmp(sel_output_type, "text") != 0 && strcasecmp(sel_output_type, "xml") != 0 && strcasecmp(sel_output_type, "csv") != 0) { printf("Invalid selection of file output type '%s'!\n", sel_output_type); return -1; } /** * Set up file descriptor for monitored data */ if (sel_output_file == NULL) { fp_monitor = stdout; } else { if (strcasecmp(sel_output_type, "xml") == 0 || strcasecmp(sel_output_type, "csv") == 0) fp_monitor = fopen(sel_output_file, "w+"); else fp_monitor = fopen(sel_output_file, "a"); if (fp_monitor == NULL) { perror("Monitoring output file open error:"); printf("Error opening '%s' output file!\n", sel_output_file); return -1; } if (strcasecmp(sel_output_type, "xml") == 0) fprintf(fp_monitor, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "%s\n", xml_root_open); } /** * get all available events on this platform */ for (i = 0; i < cap_mon->u.mon->num_events; i++) { struct pqos_monitor *mon = &cap_mon->u.mon->events[i]; all_core_evts |= mon->type; if (mon->pid_support) all_pid_evts |= mon->type; } /** * If no cores and events selected through command line * by default let's monitor all cores */ if (sel_monitor_num == 0 && sel_process_num == 0) { sel_events_max = all_core_evts; for (i = 0; i < cpu_info->num_cores; i++) { unsigned lcore = cpu_info->cores[i].lcore; uint64_t core = (uint64_t)lcore; struct core_group *pg = &sel_monitor_core_tab[sel_monitor_num]; if ((unsigned) sel_monitor_num >= DIM(sel_monitor_core_tab)) break; ret = set_cgrp(pg, uinttostr(lcore), &core, 1); if (ret != 0) { printf("Core group setup error!\n"); exit(EXIT_FAILURE); } pg->events = sel_events_max; pg->pgrp = malloc(sizeof(*pg->pgrp)); if (pg->pgrp == NULL) { printf("Error with memory allocation!\n"); exit(EXIT_FAILURE); } sel_monitor_num++; } } if (sel_process_num > 0 && sel_monitor_num > 0) { printf("Monitoring start error, process and core" " tracking can not be done simultaneously\n"); return -1; } if (!process_mode()) { /** * Make calls to pqos_mon_start - track cores */ for (i = 0; i < (unsigned)sel_monitor_num; i++) { struct core_group *cg = &sel_monitor_core_tab[i]; /* check if all available events were selected */ if (cg->events == evt_all) { cg->events = all_core_evts; sel_events_max |= all_core_evts; } else { if (all_core_evts & PQOS_PERF_EVENT_IPC) cg->events |= PQOS_PERF_EVENT_IPC; if (all_core_evts & PQOS_PERF_EVENT_LLC_MISS) cg->events |= PQOS_PERF_EVENT_LLC_MISS; } ret = pqos_mon_start(cg->num_cores, cg->cores, cg->events, (void *)cg->desc, cg->pgrp); ASSERT(ret == PQOS_RETVAL_OK); /** * The error raised also if two instances of PQoS * attempt to use the same core id. */ if (ret != PQOS_RETVAL_OK) { if (ret == PQOS_RETVAL_PERF_CTR) printf("Use -r option to start " "monitoring anyway.\n"); printf("Monitoring start error on core(s) " "%s, status %d\n", cg->desc, ret); return -1; } } } else { /** * Make calls to pqos_mon_start_pid - track PIDs */ for (i = 0; i < (unsigned)sel_process_num; i++) { struct pid_group *pg = &sel_monitor_pid_tab[i]; /* check if all available events were selected */ if (pg->events == evt_all) { pg->events = all_pid_evts; sel_events_max |= all_pid_evts; } else { if (all_pid_evts & PQOS_PERF_EVENT_IPC) pg->events |= PQOS_PERF_EVENT_IPC; if (all_pid_evts & PQOS_PERF_EVENT_LLC_MISS) pg->events |= PQOS_PERF_EVENT_LLC_MISS; } ret = pqos_mon_start_pid(sel_monitor_pid_tab[i].pid, sel_monitor_pid_tab[i].events, NULL, sel_monitor_pid_tab[i].pgrp); ASSERT(ret == PQOS_RETVAL_OK); /** * Any problem with monitoring the process? */ if (ret != PQOS_RETVAL_OK) { printf("PID %d monitoring start error," "status %d\n", sel_monitor_pid_tab[i].pid, ret); return -1; } } } return 0; }
int main (int argc, char **argv) { unsigned int i; unsigned int k; unsigned int table_size[] = {1, 2, 3, 4, 5, 23, 53}; Hash_table *ht; Hash_tuning tuning; hash_reset_tuning (&tuning); tuning.shrink_threshold = 0.3; tuning.shrink_factor = 0.707; tuning.growth_threshold = 1.5; tuning.growth_factor = 2.0; tuning.is_n_buckets = true; if (1 < argc) { unsigned int seed; if (get_seed (argv[1], &seed) != 0) { fprintf (stderr, "invalid seed: %s\n", argv[1]); exit (EXIT_FAILURE); } srand (seed); } for (i = 0; i < ARRAY_CARDINALITY (table_size); i++) { size_t sz = table_size[i]; ht = hash_initialize (sz, NULL, hash_pjw, hash_compare_strings, NULL); ASSERT (ht); insert_new (ht, "a"); { char *str1 = strdup ("a"); char *str2; ASSERT (str1); str2 = hash_insert (ht, str1); ASSERT (str1 != str2); ASSERT (STREQ (str1, str2)); free (str1); } insert_new (ht, "b"); insert_new (ht, "c"); i = 0; ASSERT (hash_do_for_each (ht, walk, &i) == 3); ASSERT (i == 7); { void *buf[5] = { NULL }; ASSERT (hash_get_entries (ht, NULL, 0) == 0); ASSERT (hash_get_entries (ht, buf, 5) == 3); ASSERT (STREQ (buf[0], "a") || STREQ (buf[0], "b") || STREQ (buf[0], "c")); } ASSERT (hash_delete (ht, "a")); ASSERT (hash_delete (ht, "a") == NULL); ASSERT (hash_delete (ht, "b")); ASSERT (hash_delete (ht, "c")); ASSERT (hash_rehash (ht, 47)); ASSERT (hash_rehash (ht, 467)); /* Free an empty table. */ hash_clear (ht); hash_free (ht); ht = hash_initialize (sz, NULL, hash_pjw, hash_compare_strings, NULL); ASSERT (ht); insert_new (ht, "z"); insert_new (ht, "y"); insert_new (ht, "x"); insert_new (ht, "w"); insert_new (ht, "v"); insert_new (ht, "u"); hash_clear (ht); ASSERT (hash_get_n_entries (ht) == 0); hash_free (ht); /* Test pointer hashing. */ ht = hash_initialize (sz, NULL, NULL, NULL, NULL); ASSERT (ht); { char *str = strdup ("a"); ASSERT (str); insert_new (ht, "a"); insert_new (ht, str); ASSERT (hash_lookup (ht, str) == str); free (str); } hash_free (ht); } hash_reset_tuning (&tuning); tuning.shrink_threshold = 0.3; tuning.shrink_factor = 0.707; tuning.growth_threshold = 1.5; tuning.growth_factor = 2.0; tuning.is_n_buckets = true; /* Invalid tuning. */ ht = hash_initialize (4651, &tuning, hash_pjw, hash_compare_strings, hash_freer); ASSERT (!ht); /* Alternate tuning. */ tuning.growth_threshold = 0.89; /* Run with default tuning, then with custom tuning settings. */ for (k = 0; k < 2; k++) { Hash_tuning const *tune = (k == 0 ? NULL : &tuning); /* Now, each entry is malloc'd. */ ht = hash_initialize (4651, tune, hash_pjw, hash_compare_strings, hash_freer); ASSERT (ht); for (i = 0; i < 10000; i++) { unsigned int op = rand () % 10; switch (op) { case 0: case 1: case 2: case 3: case 4: case 5: { char buf[50]; char const *p = uinttostr (i, buf); char *p_dup = strdup (p); ASSERT (p_dup); insert_new (ht, p_dup); } break; case 6: { size_t n = hash_get_n_entries (ht); ASSERT (hash_rehash (ht, n + rand () % 20)); } break; case 7: { size_t n = hash_get_n_entries (ht); size_t delta = rand () % 20; if (delta < n) ASSERT (hash_rehash (ht, n - delta)); } break; case 8: case 9: { /* Delete a random entry. */ size_t n = hash_get_n_entries (ht); if (n) { size_t kk = rand () % n; void const *p; void *v; for (p = hash_get_first (ht); kk; --kk, p = hash_get_next (ht, p)) { /* empty */ } ASSERT (p); v = hash_delete (ht, p); ASSERT (v); free (v); } break; } } ASSERT (hash_table_ok (ht)); } hash_free (ht); } return 0; }