void test_linux_plpa() { dstring error = DSTRING_INIT; char* topology = NULL; int length = 0; int s, c; struct utsname name; if (uname(&name) != -1) { printf("Your Linux kernel version is: %s\n", name.release); } if (!_has_core_binding(&error)) { printf("Your Linux kernel seems not to offer core binding capabilities for PLPA!\nReason: %s\n", sge_dstring_get_string(&error)); } if (!_has_topology_information()) { printf("No topology information could by retrieved by PLPA!\n"); } else { /* get amount of sockets */ printf("Amount of sockets:\t\t%d\n", get_amount_of_sockets()); /* get amount of cores */ printf("Amount of cores:\t\t%d\n", get_total_amount_of_cores()); /* get topology */ get_topology_linux(&topology, &length); printf("Topology:\t\t\t%s\n", topology); sge_free(&topology); printf("Mapping of logical socket and core numbers to internal\n"); /* for each socket,core pair get the internal processor number */ /* try multi-mapping */ for (s = 0; s < get_amount_of_sockets(); s++) { for (c = 0; c < get_amount_of_cores(s); c++) { int* proc_ids = NULL; int amount = 0; if (get_processor_ids_linux(s, c, &proc_ids, &amount)) { int i = 0; printf("Internal processor ids for socket %5d core %5d: ", s , c); for (i = 0; i < amount; i++) { printf(" %5d", proc_ids[i]); } printf("\n"); sge_free(&proc_ids); } else { printf("Couldn't get processor ids for socket %5d core %5d\n", s, c); } } } } sge_dstring_free(&error); return; }
/****** sge_binding_hlp/get_amount_of_plpa_threads() ************************************** * NAME * get_amount_of_plpa_threads() -- Get amount of threads a specific core supports. * * SYNOPSIS * int get_amount_of_plpa_threads(int socket_number, int core_number) * * FUNCTION * Returns the amount of threads a specific core supports. * * INPUTS * int socket_number - Physical socket number starting at 0. * int core_number - Physical core number on socket starting at 0. * * RESULT * int - Amount of threads a specific core supports. * * NOTES * MT-NOTE: get_amount_of_plpa_threads() is MT safe * *******************************************************************************/ int get_amount_of_plpa_threads(int socket_number, int core_number) { int amount = 0; int *ids = NULL; /* get all processor ids on the system for a given core */ if (has_core_binding() && _has_topology_information() && get_processor_ids_linux(socket_number, core_number, &ids, &amount)) { sge_free(&ids); return amount; } return 0; }
/****** shepherd_binding/add_proc_ids_linux() ********************************** * NAME * add_proc_ids_linux() -- Adds the processor ids of a core to an existing array. * * SYNOPSIS * static bool add_proc_ids_linux(int socket, int core, int** proc_id, int* * proc_id_size) * * FUNCTION * Adds the Linux internal processor ids of a specific core (which is described * via the logicial socket and core number) to an array. The length of the array * is updated. If the array point to NULL then a new array is allocated. The array * has to be freed from outside. * * INPUTS * int socket - Logical socket number (beginning with 0 without holes) * int core - Logical core number on the given socket (beginning with 0) * * OUTPUTS * int** proc_id - Array of Linux internal processor ids. * int* proc_id_size - Size of the array. * * RESULT * static bool - Returns true when the proc_id array was updated successfuly, * false when something went wrong (like not finding the core). * * NOTES * MT-NOTE: add_proc_ids_linux() is MT safe * *******************************************************************************/ static bool add_proc_ids_linux(int socket, int core, int** proc_id, int* proc_id_size) { /* OS internal processor IDs for a given logical socket, core pair */ int* pids = NULL; int pids_size = 0; int retval = true; if (proc_id_size == NULL || proc_id == NULL) return false; /* get processor ids */ if (get_processor_ids_linux(socket, core, &pids, &pids_size) && pids_size > 0 && pids != NULL) { /* append the processor ids to the given proc_id array */ /* grow proc_id array */ (*proc_id) = (int*) realloc((*proc_id), ((*proc_id_size) + pids_size) * sizeof(int)); if (*proc_id != NULL) { int i = 0; /* copy all processor ids */ for (i = (*proc_id_size); i < (*proc_id_size) + pids_size; i++) { (*proc_id)[i] = pids[i-(*proc_id_size)]; } } else { retval = false; } /* update output size */ (*proc_id_size) += pids_size; } else { retval = false; } sge_free(&pids); return retval; }
/****** sge_binding_hlp/get_topology_linux() *********************************** * NAME * get_topology_linux() -- Creates the topology string for the current host. * * SYNOPSIS * bool get_topology_linux(char** topology, int* length) * * FUNCTION * Creates the topology string for the current host. When it was created * it has top be freed from outside. * * INPUTS * char** topology - The topology string for the current host. * int* length - The length of the topology string. * * RESULT * bool - when true the topology string could be generated (and memory * is allocated otherwise false * * NOTES * MT-NOTE: get_topology_linux() is MT safe * *******************************************************************************/ bool get_topology_linux(char** topology, int* length) { bool success = false; /* initialize length of topology string */ (*length) = 0; int has_topology = 0; /* check if topology is supported via PLPA */ if (plpa_have_topology_information(&has_topology) == 0 && has_topology == 1) { int num_sockets, max_socket_id; /* topology string */ dstring d_topology = DSTRING_INIT; /* build the topology string */ if (plpa_get_socket_info(&num_sockets, &max_socket_id) == 0) { int num_cores, max_core_id, ctr_cores, ctr_sockets, ctr_threads; char* s = "S"; /* socket */ char* c = "C"; /* core */ char* t = "T"; /* thread */ for (ctr_sockets = 0; ctr_sockets < num_sockets; ctr_sockets++) { int socket_id; /* internal socket id */ /* append new socket */ sge_dstring_append_char(&d_topology, *s); (*length)++; /* for each socket get the number of cores */ if (plpa_get_socket_id(ctr_sockets, &socket_id) != 0) { /* error while getting the internal socket id out of the logical */ continue; } /* get information about this socket */ if (plpa_get_core_info(socket_id, &num_cores, &max_core_id) == 0) { /* for thread counting */ int* proc_ids = NULL; int amount_of_threads = 0; /* check each core */ for (ctr_cores = 0; ctr_cores < num_cores; ctr_cores++) { sge_dstring_append_char(&d_topology, *c); (*length)++; /* check if the core has threads */ if (get_processor_ids_linux(ctr_sockets, ctr_cores, &proc_ids, &amount_of_threads) && amount_of_threads > 1) { /* print the threads */ for (ctr_threads = 0; ctr_threads < amount_of_threads; ctr_threads++) { sge_dstring_append_char(&d_topology, *t); (*length)++; } } sge_free(&proc_ids); } } } /* for each socket */ if ((*length) != 0) { /* convert d_topolgy into topology */ (*length)++; /* we need `\0` at the end */ /* copy element */ (*topology) = sge_strdup(NULL, sge_dstring_get_string(&d_topology)); success = true; } sge_dstring_free(&d_topology); } } return success; }