libsystem: proc: add proc_get_buddyinfo()
authorWaLyong Cho <walyong.cho@samsung.com>
Fri, 11 Nov 2016 04:38:06 +0000 (13:38 +0900)
committerWaLyong Cho <walyong.cho@samsung.com>
Fri, 11 Nov 2016 04:41:19 +0000 (13:41 +0900)
To get a zone info from /proc/buddyinfo, add new api
proc_get_buddyinfo().

Change-Id: Id88cb14e9bec057b72a53820fde6a66955cd77a8
Signed-off-by: WaLyong Cho <walyong.cho@samsung.com>
src/libsystem/proc.c
src/libsystem/proc.h

index d429cf3..6a3d3df 100644 (file)
@@ -357,3 +357,66 @@ int proc_get_meminfo(struct meminfo *mi, enum meminfo_mask mask) {
 
         return 0;
 }
+
+void proc_buddyinfo_free(struct buddyinfo *bi) {
+        if (!bi)
+                return;
+
+        free(bi->zone);
+        free(bi);
+}
+
+int proc_get_buddyinfo(const char *zone, struct buddyinfo **bi) {
+        _cleanup_fclose_ FILE *f = NULL;
+        char buf[LINE_MAX];
+
+        assert(zone);
+        assert(bi);
+
+        f = fopen("/proc/buddyinfo", "re");
+        if (!f)
+                return -errno;
+
+        for (;;) {
+                _cleanup_buddyinfo_free_ struct buddyinfo *b = NULL;
+                int n;
+
+                if (!fgets(buf, sizeof(buf), f)) {
+                        if (ferror(f))
+                                return -errno;
+
+                        break;
+                }
+
+                b = new0(struct buddyinfo, 1);
+                if (!b)
+                        return -ENOMEM;
+
+                n = sscanf(buf, "Node %d, zone %m[^ ] %d %d %d %d %d %d %d %d %d %d %d",
+                           &b->node,
+                           &b->zone,
+                           &b->page[PAGE_4K],
+                           &b->page[PAGE_8K],
+                           &b->page[PAGE_16K],
+                           &b->page[PAGE_32K],
+                           &b->page[PAGE_64K],
+                           &b->page[PAGE_128K],
+                           &b->page[PAGE_256K],
+                           &b->page[PAGE_512K],
+                           &b->page[PAGE_1M],
+                           &b->page[PAGE_2M],
+                           &b->page[PAGE_4M]);
+                if (n != 13)
+                        break;
+
+                if (!streq(zone, b->zone))
+                        continue;
+
+                *bi = b;
+                b = NULL;
+
+                return 0;
+        }
+
+        return -ENODATA;
+}
index 935db2d..995cd00 100644 (file)
@@ -362,6 +362,73 @@ enum meminfo_id meminfo_string_to_id(const char *str);
 int proc_get_meminfo(struct meminfo *mi, enum meminfo_mask mask);
 
 /**
+ * /proc/buddyinfo page index
+ */
+enum {
+        PAGE_4K = 0,
+        PAGE_8K,
+        PAGE_16K,
+        PAGE_32K,
+        PAGE_64K,
+        PAGE_128K,
+        PAGE_256K,
+        PAGE_512K,
+        PAGE_1M,
+        PAGE_2M,
+        PAGE_4M,
+        PAGE_MAX,
+};
+
+/**
+ * A zone buddy info
+ */
+struct buddyinfo {
+        /**
+         * Zone name
+         */
+        char *zone;
+        /**
+         * Node number
+         */
+        int node;
+        /**
+         * Each pages size
+         */
+        int page[PAGE_MAX];
+};
+
+/**
+ * @brief free struct buddyinfo
+ *
+ * @param bi a buddyinfo
+ */
+void proc_buddyinfo_free(struct buddyinfo *bi);
+
+static inline void buddyinfo_freep(struct buddyinfo **bi)
+{
+        proc_buddyinfo_free(*bi);
+}
+
+/**
+ * Declare struct buddyinfo with cleanup attribute. Allocated struct
+ * buddyinfo is destroyed on going out the scope.
+ */
+#define _cleanup_buddyinfo_free_ _cleanup_(buddyinfo_freep)
+
+/**
+ * @brief Parse a zone in /proc/buddyinfo
+ *
+ * @param zone A zone to parse such like "Normal"
+ *
+ * @param bi Allocated and parsed buddyinfo for given zone. This value
+ * has to be destroyed by caller. #_cleanup_buddyinfo_free_ is useful
+ * to make autofree this value.
+ *
+ * @return 0 on success, -errno on failure.
+ */
+int proc_get_buddyinfo(const char *zone, struct buddyinfo **bi);
+
+/**
  * @}
  */