The attached patch implements a "linesize" cache attribute. You now get
things like
      L3Cache #0 (8192KB line=64)
        L2Cache #0 (256KB line=64)
          L1Cache #0 (32KB line=64)


>> Talking about caches, one thing we need to think about is Instruction
>> caches (we only gather Data and Unified caches on Linux so far).
>>     
> Why is runtime icache information important? :)
>   

Some people manually optimizing their kernels want this kind of info as
well as TLB size for instance...

Brice

>From 51c2b86df81b17ac5cdc4cfe6bbdaf42eb554b4f Mon Sep 17 00:00:00 2001
From: Brice Goglin <bgog...@debian.org>
List-Post: hwloc-devel@lists.open-mpi.org
Date: Tue, 25 May 2010 22:55:26 +0200
Subject: [PATCH] Add linesize cache attribute

---
 include/hwloc.h          |    1 +
 src/topology-aix.c       |    1 +
 src/topology-darwin.c    |    1 +
 src/topology-linux.c     |   11 +++++++++++
 src/topology-synthetic.c |    1 +
 src/topology-windows.c   |    2 ++
 src/topology-x86.c       |    1 +
 src/topology-xml.c       |   10 ++++++++++
 src/topology.c           |    2 ++
 src/traversal.c          |    5 +++--
 10 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/include/hwloc.h b/include/hwloc.h
index 1f275d5..c3a1b38 100644
--- a/include/hwloc.h
+++ b/include/hwloc.h
@@ -302,6 +302,7 @@ union hwloc_obj_attr_u {
   struct hwloc_cache_attr_s {
     uint64_t size;			  /**< \brief Size of cache in bytes */
     unsigned depth;			  /**< \brief Depth of cache */
+    unsigned linesize;			  /**< \brief Cache-line size in bytes */
   } cache;
   /** \brief Machine-specific Object Attributes */
   struct hwloc_machine_attr_s {
diff --git a/src/topology-aix.c b/src/topology-aix.c
index b6bfe8d..886aed6 100644
--- a/src/topology-aix.c
+++ b/src/topology-aix.c
@@ -214,6 +214,7 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
 	break;
       case HWLOC_OBJ_CACHE:
 	obj->attr->cache.size = 0; /* TODO: ? */
+	obj->attr->cache.linesize = 0; /* TODO: ? */
 	obj->attr->cache.depth = 2;
 	break;
       case HWLOC_OBJ_GROUP:
diff --git a/src/topology-darwin.c b/src/topology-darwin.c
index 5d2d157..6a9f7b5 100644
--- a/src/topology-darwin.c
+++ b/src/topology-darwin.c
@@ -122,6 +122,7 @@ hwloc_look_darwin(struct hwloc_topology *topology)
                 i, j, obj->cpuset);
             obj->attr->cache.depth = i;
             obj->attr->cache.size = cachesize[i];
+            obj->attr->cache.linesize = 0; /* TODO */
           } else {
             hwloc_debug_1arg_cpuset("node %u has cpuset %s\n",
                 j, obj->cpuset);
diff --git a/src/topology-linux.c b/src/topology-linux.c
index fcc8274..c35327b 100644
--- a/src/topology-linux.c
+++ b/src/topology-linux.c
@@ -1365,6 +1365,7 @@ look_sysfscpu(struct hwloc_topology *topology, const char *path)
 	struct hwloc_obj *cache;
 	hwloc_cpuset_t cacheset;
 	unsigned long kB = 0;
+	unsigned linesize = 0;
 	int depth; /* 0 for L1, .... */

 	/* get the cache level depth */
@@ -1403,6 +1404,15 @@ look_sysfscpu(struct hwloc_topology *topology, const char *path)
 	  fclose(fd);
 	}

+	/* get the line size */
+	sprintf(mappath, "%s/cpu%d/cache/index%d/coherency_line_size", path, i, j);
+	fd = hwloc_fopen(mappath, "r", topology->backend_params.sysfs.root_fd);
+	if (fd) {
+	  if (fgets(str2,sizeof(str2), fd))
+	    linesize = atol(str2); /* in bytes */
+	  fclose(fd);
+	}
+
 	sprintf(mappath, "%s/cpu%d/cache/index%d/shared_cpu_map", path, i, j);
 	cacheset = hwloc_parse_cpumap(mappath, topology->backend_params.sysfs.root_fd);
         if (cacheset) {
@@ -1415,6 +1425,7 @@ look_sysfscpu(struct hwloc_topology *topology, const char *path)
             cache = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1);
             cache->attr->cache.size = kB << 10;
             cache->attr->cache.depth = depth+1;
+            cache->attr->cache.linesize = linesize;
             cache->cpuset = cacheset;
             hwloc_debug_1arg_cpuset("cache depth %d has cpuset %s\n",
                        depth, cacheset);
diff --git a/src/topology-synthetic.c b/src/topology-synthetic.c
index fe37d20..99e64c4 100644
--- a/src/topology-synthetic.c
+++ b/src/topology-synthetic.c
@@ -274,6 +274,7 @@ hwloc__look_synthetic(struct hwloc_topology *topology,
       break;
     case HWLOC_OBJ_CACHE:
       obj->attr->cache.depth = topology->backend_params.synthetic.depth[level];
+      obj->attr->cache.linesize = 64;
       if (obj->attr->cache.depth == 1)
 	/* 32Kb in L1 */
 	obj->attr->cache.size = 32*1024;
diff --git a/src/topology-windows.c b/src/topology-windows.c
index 3193652..31313b0 100644
--- a/src/topology-windows.c
+++ b/src/topology-windows.c
@@ -284,6 +284,7 @@ hwloc_look_windows(struct hwloc_topology *topology)
 	    }
 	  case HWLOC_OBJ_CACHE:
 	    obj->attr->cache.size = procInfo[i].Cache.Size;
+	    obj->attr->cache.linesize = procInfo[i].Cache.LineSize;
 	    obj->attr->cache.depth = procInfo[i].Cache.Level;
 	    break;
 	  case HWLOC_OBJ_GROUP:
@@ -395,6 +396,7 @@ hwloc_look_windows(struct hwloc_topology *topology)
 	    }
 	  case HWLOC_OBJ_CACHE:
 	    obj->attr->cache.size = procInfo->Cache.CacheSize;
+	    obj->attr->cache.linesize = procInfo->Cache.LineSize;
 	    obj->attr->cache.depth = procInfo->Cache.Level;
 	    break;
 	  default:
diff --git a/src/topology-x86.c b/src/topology-x86.c
index 653353c..8946685 100644
--- a/src/topology-x86.c
+++ b/src/topology-x86.c
@@ -333,6 +333,7 @@ static void summarize(hwloc_topology_t topology, struct procinfo *infos, unsigne
           cache = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, cacheid);
           cache->attr->cache.depth = level;
           cache->attr->cache.size = infos[i].cache[l].size;
+          cache->attr->cache.linesize = infos[i].cache[l].linesize;
           cache->cpuset = cache_cpuset;
           hwloc_debug_2args_cpuset("os L%u cache %u has cpuset %s\n",
               level, cacheid, cache_cpuset);
diff --git a/src/topology-xml.c b/src/topology-xml.c
index ae11fee..0fec2ea 100644
--- a/src/topology-xml.c
+++ b/src/topology-xml.c
@@ -137,6 +137,14 @@ hwloc__xml_import_object_attr(struct hwloc_topology *topology __hwloc_attribute_
       fprintf(stderr, "ignoring cache_size attribute for non-cache object type\n");
   }

+  else if (!strcmp(name, "cache_linesize")) {
+    unsigned long lvalue = strtoul(value, NULL, 10);
+    if (obj->type == HWLOC_OBJ_CACHE)
+      obj->attr->cache.linesize = lvalue;
+    else
+      fprintf(stderr, "ignoring cache_linesize attribute for non-cache object type\n");
+  }
+
   else if (!strcmp(name, "local_memory"))
     obj->memory.local_memory = strtoull(value, NULL, 10);

@@ -498,6 +506,8 @@ hwloc__xml_export_object (hwloc_topology_t topology, hwloc_obj_t obj, xmlNodePtr
     xmlNewProp(node, BAD_CAST "cache_size", BAD_CAST tmp);
     sprintf(tmp, "%u", obj->attr->cache.depth);
     xmlNewProp(node, BAD_CAST "depth", BAD_CAST tmp);
+    sprintf(tmp, "%u", (unsigned) obj->attr->cache.linesize);
+    xmlNewProp(node, BAD_CAST "cache_linesize", BAD_CAST tmp);
     break;
   case HWLOC_OBJ_GROUP:
     sprintf(tmp, "%u", obj->attr->group.depth);
diff --git a/src/topology.c b/src/topology.c
index 267c7e3..9b67cbb 100644
--- a/src/topology.c
+++ b/src/topology.c
@@ -730,6 +730,8 @@ hwloc__insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t cur,
 	  case HWLOC_OBJ_CACHE:
 	    merge_sizes(obj, child, attr->cache.size);
 	    check_sizes(obj, child, attr->cache.size);
+	    merge_sizes(obj, child, attr->cache.linesize);
+	    check_sizes(obj, child, attr->cache.linesize);
 	    break;
 	  default:
 	    break;
diff --git a/src/traversal.c b/src/traversal.c
index f9d5346..9c36d9a 100644
--- a/src/traversal.c
+++ b/src/traversal.c
@@ -225,9 +225,10 @@ hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t

   switch (obj->type) {
   case HWLOC_OBJ_CACHE:
-    hwloc_snprintf(specific, sizeof(specific), "%lu%s",
+    hwloc_snprintf(specific, sizeof(specific), "%lu%s%sline=%u",
 		   (unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
-		   hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose));
+		   hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose),
+		   separator, obj->attr->cache.linesize);
     break;
   default:
     break;
-- 
1.7.0

Reply via email to