aboutsummaryrefslogtreecommitdiffstats
path: root/plpa-1.3.2/src/libplpa/plpa_map.c
diff options
context:
space:
mode:
authorDaniel Lange <DLange@git.local>2016-04-11 13:00:27 +0200
committerDaniel Lange <DLange@git.local>2016-04-11 13:00:27 +0200
commit283707c5e5bc436b78ea23bf5500cb6b16a01148 (patch)
treeb977131bbbb4c3bd8ade370aab2e4fc913440c04 /plpa-1.3.2/src/libplpa/plpa_map.c
parentbea9b4798717b6f4e31085506dfc179eeb8dc17c (diff)
downloaddebian_htop-283707c5e5bc436b78ea23bf5500cb6b16a01148.tar.gz
debian_htop-283707c5e5bc436b78ea23bf5500cb6b16a01148.tar.bz2
debian_htop-283707c5e5bc436b78ea23bf5500cb6b16a01148.zip
Imported Upstream version 0.9upstream/0.9
Diffstat (limited to 'plpa-1.3.2/src/libplpa/plpa_map.c')
-rw-r--r--plpa-1.3.2/src/libplpa/plpa_map.c1060
1 files changed, 1060 insertions, 0 deletions
diff --git a/plpa-1.3.2/src/libplpa/plpa_map.c b/plpa-1.3.2/src/libplpa/plpa_map.c
new file mode 100644
index 0000000..89e107f
--- /dev/null
+++ b/plpa-1.3.2/src/libplpa/plpa_map.c
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (c) 2007-2008 Cisco Systems, Inc. All rights reserved.
+ *
+ * Portions of this file originally contributed by Advanced Micro
+ * Devices, Inc. See notice below.
+ */
+/* ============================================================
+ License Agreement
+
+ Copyright (c) 2006, 2007 Advanced Micro Devices, Inc.
+ All rights reserved.
+
+ Redistribution and use in any form of this material and any product
+ thereof including software in source or binary forms, along with any
+ related documentation, with or without modification ("this material"),
+ is permitted provided that the following conditions are met:
+
+ + Redistributions of source code of any software must retain the above
+ copyright notice and all terms of this license as part of the code.
+
+ + Redistributions in binary form of any software must reproduce the
+ above copyright notice and all terms of this license in any related
+ documentation and/or other materials.
+
+ + Neither the names nor trademarks of Advanced Micro Devices, Inc. or
+ any copyright holders or contributors may be used to endorse or
+ promote products derived from this material without specific prior
+ written permission.
+
+ + Notice about U.S. Government restricted rights: This material is
+ provided with "RESTRICTED RIGHTS." Use, duplication or disclosure by
+ the U.S. Government is subject to the full extent of restrictions set
+ forth in FAR52.227 and DFARS252.227 et seq., or any successor or
+ applicable regulations. Use of this material by the U.S. Government
+ constitutes acknowledgment of the proprietary rights of Advanced Micro
+ Devices, Inc.
+ and any copyright holders and contributors.
+
+ + ANY BREACH OF ANY TERM OF THIS LICENSE SHALL RESULT IN THE IMMEDIATE
+ REVOCATION OF ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE THIS MATERIAL.
+
+ THIS MATERIAL IS PROVIDED BY ADVANCED MICRO DEVICES, INC. AND ANY
+ COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" IN ITS CURRENT CONDITION
+ AND WITHOUT ANY REPRESENTATIONS, GUARANTEE, OR WARRANTY OF ANY KIND OR
+ IN ANY WAY RELATED TO SUPPORT, INDEMNITY, ERROR FREE OR UNINTERRUPTED
+ OPERATION, OR THAT IT IS FREE FROM DEFECTS OR VIRUSES. ALL
+ OBLIGATIONS ARE HEREBY DISCLAIMED - WHETHER EXPRESS, IMPLIED, OR
+ STATUTORY - INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
+ TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, ACCURACY,
+ COMPLETENESS, OPERABILITY, QUALITY OF SERVICE, OR NON-INFRINGEMENT. IN
+ NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR ANY COPYRIGHT HOLDERS
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ USE, REVENUE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED OR BASED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY RELATED
+ TO THIS MATERIAL, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ THE ENTIRE AND AGGREGATE LIABILITY OF ADVANCED MICRO DEVICES, INC. AND
+ ANY COPYRIGHT HOLDERS AND CONTRIBUTORS SHALL NOT EXCEED TEN DOLLARS
+ (US $10.00). ANYONE REDISTRIBUTING OR ACCESSING OR USING THIS MATERIAL
+ ACCEPTS THIS ALLOCATION OF RISK AND AGREES TO RELEASE ADVANCED MICRO
+ DEVICES, INC. AND ANY COPYRIGHT HOLDERS AND CONTRIBUTORS FROM ANY AND
+ ALL LIABILITIES, OBLIGATIONS, CLAIMS, OR DEMANDS IN EXCESS OF TEN
+ DOLLARS (US $10.00). THE FOREGOING ARE ESSENTIAL TERMS OF THIS LICENSE
+ AND, IF ANY OF THESE TERMS ARE CONSTRUED AS UNENFORCEABLE, FAIL IN
+ ESSENTIAL PURPOSE, OR BECOME VOID OR DETRIMENTAL TO ADVANCED MICRO
+ DEVICES, INC. OR ANY COPYRIGHT HOLDERS OR CONTRIBUTORS FOR ANY REASON,
+ THEN ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE THIS MATERIAL SHALL
+ TERMINATE IMMEDIATELY. MOREOVER, THE FOREGOING SHALL SURVIVE ANY
+ EXPIRATION OR TERMINATION OF THIS LICENSE OR ANY AGREEMENT OR ACCESS
+ OR USE RELATED TO THIS MATERIAL.
+
+ NOTICE IS HEREBY PROVIDED, AND BY REDISTRIBUTING OR ACCESSING OR USING
+ THIS MATERIAL SUCH NOTICE IS ACKNOWLEDGED, THAT THIS MATERIAL MAY BE
+ SUBJECT TO RESTRICTIONS UNDER THE LAWS AND REGULATIONS OF THE UNITED
+ STATES OR OTHER COUNTRIES, WHICH INCLUDE BUT ARE NOT LIMITED TO, U.S.
+ EXPORT CONTROL LAWS SUCH AS THE EXPORT ADMINISTRATION REGULATIONS AND
+ NATIONAL SECURITY CONTROLS AS DEFINED THEREUNDER, AS WELL AS STATE
+ DEPARTMENT CONTROLS UNDER THE U.S. MUNITIONS LIST. THIS MATERIAL MAY
+ NOT BE USED, RELEASED, TRANSFERRED, IMPORTED, EXPORTED AND/OR RE-
+ EXPORTED IN ANY MANNER PROHIBITED UNDER ANY APPLICABLE LAWS, INCLUDING
+ U.S. EXPORT CONTROL LAWS REGARDING SPECIFICALLY DESIGNATED PERSONS,
+ COUNTRIES AND NATIONALS OF COUNTRIES SUBJECT TO NATIONAL SECURITY
+ CONTROLS.
+ MOREOVER,
+ THE FOREGOING SHALL SURVIVE ANY EXPIRATION OR TERMINATION OF ANY
+ LICENSE OR AGREEMENT OR ACCESS OR USE RELATED TO THIS MATERIAL.
+
+ This license forms the entire agreement regarding the subject matter
+ hereof and supersedes all proposals and prior discussions and writings
+ between the parties with respect thereto. This license does not affect
+ any ownership, rights, title, or interest in, or relating to, this
+ material. No terms of this license can be modified or waived, and no
+ breach of this license can be excused, unless done so in a writing
+ signed by all affected parties. Each term of this license is
+ separately enforceable. If any term of this license is determined to
+ be or becomes unenforceable or illegal, such term shall be reformed to
+ the minimum extent necessary in order for this license to remain in
+ effect in accordance with its terms as modified by such reformation.
+ This license shall be governed by and construed in accordance with the
+ laws of the State of Texas without regard to rules on conflicts of law
+ of any state or jurisdiction or the United Nations Convention on the
+ International Sale of Goods. All disputes arising out of this license
+ shall be subject to the jurisdiction of the federal and state courts
+ in Austin, Texas, and all defenses are hereby waived concerning
+ personal jurisdiction and venue of these courts.
+ ============================================================ */
+
+#include "plpa_config.h"
+#include "plpa.h"
+#include "plpa_internal.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+typedef struct tuple_t_ {
+ int processor_id, socket_id, core_id, online;
+} tuple_t;
+
+static const char *sysfs_mount = "/sys";
+static int supported = 0;
+static int num_processors = -1;
+static int max_processor_id = -1;
+static int num_sockets = -1;
+static int max_socket_id = -1;
+static int *max_core_id = NULL;
+static int *num_cores = NULL;
+static int max_core_id_overall = -1;
+static tuple_t *map_processor_id_to_tuple = NULL;
+static tuple_t **map_tuple_to_processor_id = NULL;
+static PLPA_NAME(cache_behavior_t) cache_behavior = PLPA_NAME_CAPS(CACHE_IGNORE);
+
+static void clear_cache(void)
+{
+ if (NULL != max_core_id) {
+ free(max_core_id);
+ max_core_id = NULL;
+ }
+ if (NULL != num_cores) {
+ free(num_cores);
+ num_cores = NULL;
+ }
+ if (NULL != map_processor_id_to_tuple) {
+ free(map_processor_id_to_tuple);
+ map_processor_id_to_tuple = NULL;
+ }
+ if (NULL != map_tuple_to_processor_id) {
+ free(map_tuple_to_processor_id);
+ map_tuple_to_processor_id = NULL;
+ }
+
+ num_processors = max_processor_id = -1;
+ num_sockets = max_socket_id = -1;
+ max_core_id_overall = -1;
+}
+
+static void load_cache(void)
+{
+ int i, j, k, invalid_entry, fd, found_online;
+ char path[PATH_MAX], buf[8];
+ PLPA_NAME(cpu_set_t) valid_processors;
+ PLPA_NAME(cpu_set_t) *cores_on_sockets;
+ int found;
+ DIR *dir;
+ struct dirent dentry, *dentryp = NULL;
+
+#if PLPA_DEBUG
+ char *temp = getenv("PLPA_SYSFS_MOUNT");
+ if (temp) {
+ sysfs_mount = temp;
+ }
+#endif
+
+ /* Check for the parent directory */
+ sprintf(path, "%s/devices/system/cpu", sysfs_mount);
+ if (access(path, R_OK|X_OK)) {
+ return;
+ }
+
+ dir = opendir(path);
+ if (NULL == dir) {
+ return;
+ }
+
+ /* Catch all entries of format "cpu%d", count them and maintain
+ max_processor_id */
+ num_processors = 0;
+ PLPA_CPU_ZERO(&valid_processors);
+ do {
+ int ret = readdir_r(dir, &dentry, &dentryp);
+ if (0 != ret) {
+ closedir(dir);
+ clear_cache();
+ return;
+ }
+
+ if (dentryp) {
+ int cpuid;
+
+ ret = sscanf(dentryp->d_name, "cpu%d", &cpuid);
+ if (1 == ret) {
+ ++num_processors;
+ if (cpuid >= PLPA_BITMASK_CPU_MAX) {
+ closedir(dir);
+ clear_cache();
+ return;
+ } else if (cpuid > max_processor_id) {
+ max_processor_id = cpuid;
+ }
+ PLPA_CPU_SET(cpuid, &valid_processors);
+ }
+ }
+ } while (NULL != dentryp);
+ closedir(dir);
+
+ /* If we found no processors, then we have no topology info */
+ if (0 == num_processors) {
+ clear_cache();
+ return;
+ }
+
+ /* Malloc space for the first map (processor ID -> tuple).
+ Include enough space for one invalid entry. */
+ map_processor_id_to_tuple = malloc(sizeof(tuple_t) *
+ (max_processor_id + 2));
+ if (NULL == map_processor_id_to_tuple) {
+ clear_cache();
+ return;
+ }
+ for (i = 0; i <= max_processor_id; ++i) {
+ if (PLPA_CPU_ISSET(i, &valid_processors)) {
+ map_processor_id_to_tuple[i].processor_id = i;
+ } else {
+ map_processor_id_to_tuple[i].processor_id = -1;
+ }
+ map_processor_id_to_tuple[i].socket_id = -1;
+ map_processor_id_to_tuple[i].core_id = -1;
+ }
+ /* Set the invalid entry */
+ invalid_entry = i;
+ map_processor_id_to_tuple[invalid_entry].processor_id = -1;
+ map_processor_id_to_tuple[invalid_entry].socket_id = -1;
+ map_processor_id_to_tuple[invalid_entry].core_id = -1;
+
+ /* Build a cached map of (socket,core) tuples */
+ for (found = 0, i = 0; i <= max_processor_id; ++i) {
+
+ /* Check for invalid processor ID */
+ if (map_processor_id_to_tuple[i].processor_id < 0) {
+ continue;
+ }
+
+ /* Read the "online" state for this processor. If the online
+ file is not there, then the kernel likely doesn't have
+ hotplug support so just assume that it's online. Some notes:
+
+ - the perms on the "online" file are root/600, so only root
+ will see this info
+ - if online is 0, then all the topology files disappear (!)
+ -- so PLPA needs to compensate for that
+ */
+ found_online = 0;
+ sprintf(path, "%s/devices/system/cpu/cpu%d/online",
+ sysfs_mount, i);
+ fd = open(path, O_RDONLY);
+ memset(buf, 0, sizeof(buf));
+ if (fd >= 0 && read(fd, buf, sizeof(buf) - 1) > 0) {
+ found_online = 1;
+ sscanf(buf, "%d", &(map_processor_id_to_tuple[i].online));
+ } else {
+ map_processor_id_to_tuple[i].online = 1;
+ }
+ if (fd >= 0) {
+ close(fd);
+ }
+
+ /* Core ID */
+ sprintf(path, "%s/devices/system/cpu/cpu%d/topology/core_id",
+ sysfs_mount, i);
+ fd = open(path, O_RDONLY);
+ if (fd >= 0) {
+ memset(buf, 0, sizeof(buf));
+ if (read(fd, buf, sizeof(buf) - 1) > 0) {
+ sscanf(buf, "%d", &(map_processor_id_to_tuple[i].core_id));
+ } else {
+ map_processor_id_to_tuple[i].core_id = -1;
+ }
+ close(fd);
+ }
+ /* Special case: we didn't find the core_id file, but we *did*
+ find the online file and the processor is offline -- then
+ just mark the core ID as "unknown" and keep going (because
+ if a processor is offline, the core_id file won't exist --
+ grumble) */
+ else if (found_online && 0 == map_processor_id_to_tuple[i].online) {
+ map_processor_id_to_tuple[i].core_id = -1;
+ }
+
+ /* Socket ID */
+ sprintf(path,
+ "%s/devices/system/cpu/cpu%d/topology/physical_package_id",
+ sysfs_mount, i);
+ fd = open(path, O_RDONLY);
+ if (fd >= 0) {
+ memset(buf, 0, sizeof(buf));
+ if (read(fd, buf, sizeof(buf) - 1) > 0) {
+ sscanf(buf, "%d", &(map_processor_id_to_tuple[i].socket_id));
+ }
+ close(fd);
+ found = 1;
+ }
+ /* Special case: we didn't find the socket_id file, but we
+ *did* find the online file and the processor is offline --
+ then just mark the socket ID as "unknown" and keep going
+ (because if a processor is offline, the socket_id file won't
+ exist -- grumble) */
+ else if (found_online && 0 == map_processor_id_to_tuple[i].online) {
+ map_processor_id_to_tuple[i].socket_id = -1;
+ }
+
+ /* Keep a running tab on the max socket number */
+ if (map_processor_id_to_tuple[i].socket_id > max_socket_id) {
+ max_socket_id = map_processor_id_to_tuple[i].socket_id;
+ }
+ }
+
+ /* If we didn't find any core_id/physical_package_id's, then we
+ don't have the topology info */
+ if (!found) {
+ clear_cache();
+ return;
+ }
+
+ /* Now that we know the max number of sockets, allocate some
+ arrays */
+ max_core_id = malloc(sizeof(int) * (max_socket_id + 1));
+ if (NULL == max_core_id) {
+ clear_cache();
+ return;
+ }
+ num_cores = malloc(sizeof(int) * (max_socket_id + 1));
+ if (NULL == num_cores) {
+ clear_cache();
+ return;
+ }
+ for (i = 0; i <= max_socket_id; ++i) {
+ num_cores[i] = -1;
+ max_core_id[i] = -1;
+ }
+
+ /* Find the max core number on each socket */
+ for (i = 0; i <= max_processor_id; ++i) {
+ if (map_processor_id_to_tuple[i].processor_id < 0 ||
+ map_processor_id_to_tuple[i].socket_id < 0) {
+ continue;
+ }
+ if (map_processor_id_to_tuple[i].core_id >
+ max_core_id[map_processor_id_to_tuple[i].socket_id]) {
+ max_core_id[map_processor_id_to_tuple[i].socket_id] =
+ map_processor_id_to_tuple[i].core_id;
+ }
+ if (max_core_id[map_processor_id_to_tuple[i].socket_id] >
+ max_core_id_overall) {
+ max_core_id_overall =
+ max_core_id[map_processor_id_to_tuple[i].socket_id];
+ }
+ }
+
+ /* Go through and count the number of unique sockets found. It
+ may not be the same as max_socket_id because there may be
+ "holes" -- e.g., sockets 0 and 3 are used, but sockets 1 and 2
+ are empty. */
+ for (j = i = 0; i <= max_socket_id; ++i) {
+ if (max_core_id[i] >= 0) {
+ ++j;
+ }
+ }
+ if (j > 0) {
+ num_sockets = j;
+ }
+
+ /* Count how many cores are available on each socket. This may
+ not be the same as max_core_id[socket_num] if there are
+ "holes". I don't know if holes can happen (i.e., if specific
+ cores can be taken offline), but what the heck... */
+ cores_on_sockets = malloc(sizeof(PLPA_NAME(cpu_set_t)) *
+ (max_socket_id + 1));
+ if (NULL == cores_on_sockets) {
+ clear_cache();
+ return;
+ }
+ for (i = 0; i <= max_socket_id; ++i) {
+ PLPA_CPU_ZERO(&(cores_on_sockets[i]));
+ }
+ for (i = 0; i <= max_processor_id; ++i) {
+ if (map_processor_id_to_tuple[i].socket_id >= 0) {
+ PLPA_CPU_SET(map_processor_id_to_tuple[i].core_id,
+ &(cores_on_sockets[map_processor_id_to_tuple[i].socket_id]));
+ }
+ }
+ for (i = 0; i <= max_socket_id; ++i) {
+ int count = 0;
+ for (j = 0; j <= max_core_id[i]; ++j) {
+ if (PLPA_CPU_ISSET(j, &(cores_on_sockets[i]))) {
+ ++count;
+ }
+ }
+ if (count > 0) {
+ num_cores[i] = count;
+ }
+ }
+ free(cores_on_sockets);
+
+ /* Now go through and build the map in the other direction:
+ (socket,core) => processor_id. This map simply points to
+ entries in the other map (i.e., it's by reference instead of by
+ value). */
+ map_tuple_to_processor_id = malloc(sizeof(tuple_t *) *
+ ((max_socket_id + 1) *
+ (max_core_id_overall + 1)));
+ if (NULL == map_tuple_to_processor_id) {
+ clear_cache();
+ return;
+ }
+ /* Compute map */
+ for (i = 0; i <= max_socket_id; ++i) {
+ for (j = 0; j <= max_core_id_overall; ++j) {
+ tuple_t **tuple_ptr = &map_tuple_to_processor_id[
+ i * (max_core_id_overall + 1) + j];
+
+ /* Default to the invalid entry in the other map, meaning
+ that this (socket,core) combination doesn't exist
+ (e.g., the core number does not exist in this socket,
+ although it does exist in other sockets). */
+ *tuple_ptr = &map_processor_id_to_tuple[invalid_entry];
+
+ /* See if this (socket,core) tuple exists in the other
+ map. If so, set this entry to point to it (overriding
+ the invalid entry default). */
+ for (k = 0; k <= max_processor_id; ++k) {
+ if (map_processor_id_to_tuple[k].socket_id == i &&
+ map_processor_id_to_tuple[k].core_id == j) {
+ *tuple_ptr = &map_processor_id_to_tuple[k];
+#if defined(PLPA_DEBUG) && PLPA_DEBUG
+ printf("Creating map [%d]: (socket %d, core %d) -> ID %d\n",
+ i * (max_core_id_overall + 1) + j,
+ i, j, k);
+#endif
+ break;
+ }
+ }
+ }
+ }
+
+ supported = 1;
+}
+
+static int cache_action(void)
+{
+ switch (cache_behavior) {
+ case PLPA_NAME_CAPS(CACHE_USE):
+ if (NULL == map_processor_id_to_tuple) {
+ load_cache();
+ }
+ break;
+
+ case PLPA_NAME_CAPS(CACHE_IGNORE):
+ clear_cache();
+ load_cache();
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+/* Return whether this kernel supports topology information or not */
+int PLPA_NAME(have_topology_information)(int *supported_arg)
+{
+ int ret;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == supported_arg) {
+ return EINVAL;
+ }
+
+ *supported_arg = supported;
+ return 0;
+}
+
+int PLPA_NAME(map_to_processor_id)(int socket_id, int core_id,
+ int *processor_id)
+{
+ int ret;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == processor_id) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for some invalid entries */
+ if (socket_id < 0 || socket_id > max_socket_id ||
+ core_id < 0 || core_id > max_core_id[socket_id]) {
+ return ENOENT;
+ }
+ /* If the mapping returns -1, then this is a non-existent
+ socket/core combo (even though they fall within the max socket
+ / max core overall values) */
+ ret = map_tuple_to_processor_id[socket_id * (max_core_id_overall + 1) +
+ core_id]->processor_id;
+ if (-1 == ret) {
+ return ENOENT;
+ }
+
+ /* Ok, all should be good -- return the mapping */
+ *processor_id = ret;
+ return 0;
+}
+
+int PLPA_NAME(map_to_socket_core)(int processor_id,
+ int *socket_id, int *core_id)
+{
+ int ret;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == socket_id || NULL == core_id) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for some invalid entries */
+ if (processor_id < 0 || processor_id > max_processor_id ||
+ map_processor_id_to_tuple[processor_id].processor_id < 0) {
+ return ENOENT;
+ }
+ ret = map_processor_id_to_tuple[processor_id].socket_id;
+ if (-1 == ret) {
+ return ENOENT;
+ }
+
+ /* Ok, all should be good -- return the mapping */
+ *socket_id = ret;
+ *core_id = map_processor_id_to_tuple[processor_id].core_id;
+ return 0;
+}
+
+/* Deprecated function */
+int PLPA_NAME(get_processor_info)(int *num_processors_arg,
+ int *max_processor_id_arg)
+{
+ return PLPA_NAME(get_processor_data)(PLPA_NAME_CAPS(COUNT_ALL),
+ num_processors_arg,
+ max_processor_id_arg);
+}
+
+int PLPA_NAME(get_processor_data)(PLPA_NAME(count_specification_t) count_spec,
+ int *num_processors_arg,
+ int *max_processor_id_arg)
+{
+ int i, ret;
+ bool match;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == max_processor_id_arg || NULL == num_processors_arg) {
+ return EINVAL;
+ }
+
+ /* If we wanted all processors, we're done */
+ if (PLPA_NAME_CAPS(COUNT_ALL) == count_spec) {
+ *num_processors_arg = num_processors;
+ *max_processor_id_arg = max_processor_id;
+ } else {
+ /* Otherwise, count the appropriate type */
+ *num_processors_arg = 0;
+ *max_processor_id_arg = 0;
+ for (i = 0; i <= max_processor_id; ++i) {
+ if (map_processor_id_to_tuple[i].processor_id >= 0) {
+ match = false;
+ switch (count_spec) {
+ case PLPA_NAME_CAPS(COUNT_ONLINE):
+ if (map_processor_id_to_tuple[i].online) {
+ match = true;
+ }
+ break;
+
+ case PLPA_NAME_CAPS(COUNT_OFFLINE):
+ if (!map_processor_id_to_tuple[i].online) {
+ match = true;
+ }
+ break;
+ default:
+ /* Just so that compilers don't complain */
+ break;
+ }
+ if (match) {
+ ++(*num_processors_arg);
+ if (*max_processor_id_arg <
+ map_processor_id_to_tuple[i].processor_id) {
+ *max_processor_id_arg =
+ map_processor_id_to_tuple[i].processor_id;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* Returns the Linux processor ID for the Nth processor (starting with
+ 0). */
+int PLPA_NAME(get_processor_id)(int processor_num,
+ PLPA_NAME(count_specification_t) count_spec,
+ int *processor_id)
+{
+ int ret, i, count;
+ bool match;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == processor_id) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for out of range params */
+ if (processor_num < 0 || processor_num > num_processors) {
+ return EINVAL;
+ }
+
+ /* Find the processor_num'th processor */
+ for (count = i = 0; i <= max_processor_id; ++i) {
+ if (map_processor_id_to_tuple[i].processor_id >= 0) {
+ match = false;
+ switch (count_spec) {
+ case PLPA_NAME_CAPS(COUNT_ONLINE):
+ if (map_processor_id_to_tuple[i].online) {
+ match = true;
+ }
+ break;
+
+ case PLPA_NAME_CAPS(COUNT_OFFLINE):
+ if (!map_processor_id_to_tuple[i].online) {
+ match = true;
+ }
+ break;
+
+ case PLPA_NAME_CAPS(COUNT_ALL):
+ match = true;
+ break;
+ }
+ if (match) {
+ if (count++ == processor_num) {
+ *processor_id = map_processor_id_to_tuple[i].processor_id;
+ return 0;
+ }
+ }
+ }
+ }
+
+ /* Didn't find it */
+ return ENODEV;
+}
+
+/* Check to see if a given Linux processor ID exists / is online.
+ Returns 0 on success. */
+int PLPA_NAME(get_processor_flags)(int processor_id,
+ int *exists_arg, int *online_arg)
+{
+ int ret, exists, online;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == exists_arg && NULL == online_arg) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for out of range params */
+ if (processor_id < 0 || processor_id > max_processor_id) {
+ return EINVAL;
+ }
+
+ exists = online = 0;
+ if (processor_id == map_processor_id_to_tuple[processor_id].processor_id) {
+ exists = 1;
+ if (map_processor_id_to_tuple[processor_id].online) {
+ online = 1;
+ }
+ }
+ if (NULL != exists_arg) {
+ *exists_arg = exists;
+ }
+ if (NULL != online_arg) {
+ *online_arg = online;
+ }
+
+ return 0;
+}
+
+/* Return the max socket number */
+int PLPA_NAME(get_socket_info)(int *num_sockets_arg, int *max_socket_id_arg)
+{
+ int ret;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == max_socket_id_arg || NULL == num_sockets_arg) {
+ return EINVAL;
+ }
+
+ /* All done */
+ *num_sockets_arg = num_sockets;
+ *max_socket_id_arg = max_socket_id;
+ return 0;
+}
+
+/* Returns the Linux socket ID for the Nth socket (starting with 0). */
+int PLPA_NAME(get_socket_id)(int socket_num, int *socket_id)
+{
+ int ret, i, j, k, count;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == socket_id) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for out of range params */
+ if (socket_num < 0 || socket_num > num_sockets) {
+ return EINVAL;
+ }
+
+ /* Find the socket_num'th socket */
+ for (count = i = 0; i <= max_socket_id; ++i) {
+ /* See if any core in this socket is active. If so, count
+ this socket */
+ for (j = 0; j <= max_core_id_overall; ++j) {
+ k = i * (max_core_id_overall + 1) + j;
+ if (map_tuple_to_processor_id[k]->processor_id >= 0) {
+ if (count++ == socket_num) {
+ *socket_id = map_tuple_to_processor_id[k]->socket_id;
+ return 0;
+ }
+ /* Ok, we found one -- skip to the end of this socket */
+ j = max_core_id_overall + 1;
+ }
+ }
+ }
+
+ /* Didn't find it */
+ return ENODEV;
+}
+
+/* Return the number of cores in a socket and the max core ID number */
+int PLPA_NAME(get_core_info)(int socket_id, int *num_cores_arg,
+ int *max_core_id_arg)
+{
+ int ret;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == max_core_id_arg || NULL == num_cores_arg) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for some invalid entries */
+ if (socket_id < 0 || socket_id > max_socket_id ||
+ -1 == max_core_id[socket_id]) {
+ return ENOENT;
+ }
+ ret = num_cores[socket_id];
+ if (-1 == ret) {
+ return ENOENT;
+ }
+
+ /* All done */
+ *num_cores_arg = ret;
+ *max_core_id_arg = max_core_id[socket_id];
+ return 0;
+}
+
+/* Given a specific socket, returns the Linux core ID for the Nth core
+ (starting with 0) */
+int PLPA_NAME(get_core_id)(int socket_id, int core_num, int *core_id)
+{
+ int ret, i, j, count;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == core_id) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for out of range params */
+ if (socket_id < 0 || socket_id > max_socket_id ||
+ core_num < 0 || core_num > max_core_id_overall) {
+ return EINVAL;
+ }
+
+ /* Find the core_num'th core */
+ for (count = i = 0, j = socket_id * (max_core_id_overall + 1);
+ i <= max_core_id_overall; ++i) {
+ if (map_tuple_to_processor_id[j + i]->processor_id >= 0) {
+ if (count++ == core_num) {
+ *core_id = map_tuple_to_processor_id[j + i]->core_id;
+ return 0;
+ }
+ }
+ }
+
+ /* Didn't find it */
+ return ENODEV;
+}
+
+/* Check to see if a given Linux (socket_id,core_id) tuple exists / is
+ online. Returns 0 on success. */
+int PLPA_NAME(get_core_flags)(int socket_id, int core_id,
+ int *exists_arg, int *online_arg)
+{
+ int ret, i, exists, online;
+
+ /* Initialize if not already done so */
+ if (!PLPA_NAME(initialized)) {
+ if (0 != (ret = PLPA_NAME(init)())) {
+ return ret;
+ }
+ }
+
+ /* If this system doesn't support mapping, sorry Charlie */
+ if (!supported) {
+ return ENOSYS;
+ }
+
+ /* Check for bozo arguments */
+ if (NULL == exists_arg && NULL == online_arg) {
+ return EINVAL;
+ }
+
+ /* Check cache behavior */
+ if (0 != (ret = cache_action())) {
+ return ret;
+ }
+
+ /* Check for out of range params */
+ if (socket_id < 0 || socket_id > max_socket_id ||
+ core_id < 0 || core_id > max_core_id_overall) {
+ return EINVAL;
+ }
+
+ exists = online = 0;
+ i = socket_id * (max_core_id_overall + 1) + core_id;
+ if (map_tuple_to_processor_id[i]->processor_id >= 0) {
+ exists = 1;
+ if (map_tuple_to_processor_id[i]->online) {
+ online = 1;
+ }
+ }
+
+ if (NULL != exists_arg) {
+ *exists_arg = exists;
+ }
+ if (NULL != online_arg) {
+ *online_arg = online;
+ }
+ return 0;
+}
+
+/* Set PLPA's caching behavior */
+int PLPA_NAME(set_cache_behavior)(PLPA_NAME(cache_behavior_t) behavior)
+{
+ switch (behavior) {
+ case PLPA_NAME_CAPS(CACHE_USE):
+ if (PLPA_NAME_CAPS(CACHE_USE) != cache_behavior) {
+ load_cache();
+ cache_behavior = PLPA_NAME_CAPS(CACHE_USE);
+ }
+ break;
+
+ case PLPA_NAME_CAPS(CACHE_IGNORE):
+ if (PLPA_NAME_CAPS(CACHE_IGNORE) != cache_behavior) {
+ clear_cache();
+ cache_behavior = PLPA_NAME_CAPS(CACHE_IGNORE);
+ }
+ break;
+
+ case PLPA_NAME_CAPS(CACHE_REFRESH):
+ if (PLPA_NAME_CAPS(CACHE_USE) != cache_behavior) {
+ return EINVAL;
+ }
+ clear_cache();
+ load_cache();
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}

© 2014-2024 Faster IT GmbH | imprint | privacy policy