summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaLyong Cho <walyong.cho@samsung.com>2016-11-10 19:36:04 +0900
committerWaLyong Cho <walyong.cho@samsung.com>2016-11-10 20:13:21 +0900
commit35bf52f9d3823fad34a70c3c4fcbad9a50b8f8c1 (patch)
tree70b378be49f7c50b8061e319e86e277a556e757c
parent3856ef0845a510859ee0969b3839f659e43ab405 (diff)
downloadlibsystem-35bf52f9d3823fad34a70c3c4fcbad9a50b8f8c1.tar.gz
libsystem-35bf52f9d3823fad34a70c3c4fcbad9a50b8f8c1.tar.bz2
libsystem-35bf52f9d3823fad34a70c3c4fcbad9a50b8f8c1.zip
libsystem: proc: add /proc/meminfo parse api
Change-Id: I74b0f5992d49428b13213aef6fcb8c200c0605d3 Signed-off-by: WaLyong Cho <walyong.cho@samsung.com>
-rw-r--r--src/Makefile.am3
-rw-r--r--src/libsystem/.gitignore1
-rw-r--r--src/libsystem/proc-meminfo-lookup.gperf67
-rw-r--r--src/libsystem/proc.c105
-rw-r--r--src/libsystem/proc.h134
5 files changed, 310 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f1ca4cf..9378c18 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,13 +66,16 @@ libsystem_la_SOURCES = \
libsystem/libsystem.c \
libsystem/libsystem.h \
libsystem/proc.c \
+ libsystem/proc-meminfo-lookup.c \
libsystem/proc-smaps-lookup.c \
libsystem/time-util.c
EXTRA_DIST += \
+ libsystem/proc-meminfo-lookup.gperf \
libsystem/proc-smaps-lookup.gperf
CLEANFILES += \
+ libsystem/proc-meminfo-lookup.c \
libsystem/proc-smaps-lookup.c
libsystem_la_CFLAGS = \
diff --git a/src/libsystem/.gitignore b/src/libsystem/.gitignore
index fe4ac25..154d18c 100644
--- a/src/libsystem/.gitignore
+++ b/src/libsystem/.gitignore
@@ -1,2 +1,3 @@
/libsystem.pc
+/proc-meminfo-lookup.c
/proc-smaps-lookup.c \ No newline at end of file
diff --git a/src/libsystem/proc-meminfo-lookup.gperf b/src/libsystem/proc-meminfo-lookup.gperf
new file mode 100644
index 0000000..1ca9fbe
--- /dev/null
+++ b/src/libsystem/proc-meminfo-lookup.gperf
@@ -0,0 +1,67 @@
+%{
+#include <assert.h>
+#include "proc.h"
+
+struct meminfo_mapping {
+ const char *name;
+ enum meminfo_id id;
+};
+typedef struct meminfo_mapping meminfo_mapping;
+%}
+meminfo_mapping;
+%language=ANSI-C
+%define slot-name name
+%define hash-function-name meminfo_mapping_hash
+%define lookup-function-name meminfo_mapping_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+MemTotal, MEMINFO_ID_MEM_TOTAL
+MemFree, MEMINFO_ID_MEM_FREE
+MemAvailable, MEMINFO_ID_MEM_AVAILABLE
+Buffers, MEMINFO_ID_BUFFERS
+Cached, MEMINFO_ID_CACHED
+SwapCached, MEMINFO_ID_SWAP_CACHED
+Active, MEMINFO_ID_ACTIVE
+Inactive, MEMINFO_ID_INACTIVE
+Active(anon), MEMINFO_ID_ACTIVE_ANON
+Inactive(anon), MEMINFO_ID_INACTIVE_ANON
+Active(file), MEMINFO_ID_ACTIVE_FILE
+Inactive(file), MEMINFO_ID_INACTIVE_FILE
+Unevictable, MEMINFO_ID_UNEVICTABLE
+Mlocked, MEMINFO_ID_MLOCKED
+HighTotal, MEMINFO_ID_HIGH_TOTAL
+HighFree, MEMINFO_ID_HIGH_FREE
+LowTotal, MEMINFO_ID_LOW_TOTAL
+LowFree, MEMINFO_ID_LOW_FREE
+SwapTotal, MEMINFO_ID_SWAP_TOTAL
+SwapFree, MEMINFO_ID_SWAP_FREE
+Dirty, MEMINFO_ID_DIRTY
+Writeback, MEMINFO_ID_WRITEBACK
+AnonPages, MEMINFO_ID_ANON_PAGES
+Mapped, MEMINFO_ID_MAPPED
+Shmem, MEMINFO_ID_SHMEM
+Slab, MEMINFO_ID_SLAB
+SReclaimable, MEMINFO_ID_SRECLAIMABLE
+SUnreclaim, MEMINFO_ID_SUNRECLAIM
+KernelStack, MEMINFO_ID_KERNEL_STACK
+PageTables, MEMINFO_ID_PAGE_TABLES
+NFS_Unstable, MEMINFO_ID_NFS_UNSTABLE
+Bounce, MEMINFO_ID_BOUNCE
+WritebackTmp, MEMINFO_ID_WRITEBACK_TMP
+CommitLimit, MEMINFO_ID_COMMIT_LIMIT
+Committed_AS, MEMINFO_ID_COMMITTED_AS
+VmallocTotal, MEMINFO_ID_VMALLOC_TOTAL
+VmallocUsed, MEMINFO_ID_VMALLOC_USED
+VmallocChunk, MEMINFO_ID_VMALLOC_CHUNK
+%%
+enum meminfo_id meminfo_string_to_id(const char *str)
+{
+ const struct meminfo_mapping *i;
+
+ assert(str);
+ i = meminfo_mapping_lookup(str, strlen(str));
+ return i ? i->id : MEMINFO_ID_INVALID;
+}
diff --git a/src/libsystem/proc.c b/src/libsystem/proc.c
index 38d5b93..d429cf3 100644
--- a/src/libsystem/proc.c
+++ b/src/libsystem/proc.c
@@ -252,3 +252,108 @@ on_error:
smaps_free(m);
return r;
}
+
+static const char* const meminfo_string_lookup[MEMINFO_ID_MAX] = {
+ [MEMINFO_ID_MEM_TOTAL] = "MemTotal",
+ [MEMINFO_ID_MEM_FREE] = "MemFree",
+ [MEMINFO_ID_MEM_AVAILABLE] = "MemAvailable",
+ [MEMINFO_ID_BUFFERS] = "Buffers",
+ [MEMINFO_ID_CACHED] = "Cached",
+ [MEMINFO_ID_SWAP_CACHED] = "SwapCached",
+ [MEMINFO_ID_ACTIVE] = "Active",
+ [MEMINFO_ID_INACTIVE] = "Inactive",
+ [MEMINFO_ID_ACTIVE_ANON] = "Active(anon)",
+ [MEMINFO_ID_INACTIVE_ANON] = "Inactive(anon)",
+ [MEMINFO_ID_ACTIVE_FILE] = "Active(file)",
+ [MEMINFO_ID_INACTIVE_FILE] = "Inactive(file)",
+ [MEMINFO_ID_UNEVICTABLE] = "Unevictable",
+ [MEMINFO_ID_MLOCKED] = "Mlocked",
+ [MEMINFO_ID_HIGH_TOTAL] = "HighTotal",
+ [MEMINFO_ID_HIGH_FREE] = "HighFree",
+ [MEMINFO_ID_LOW_TOTAL] = "LowTotal",
+ [MEMINFO_ID_LOW_FREE] = "LowFree",
+ [MEMINFO_ID_SWAP_TOTAL] = "SwapTotal",
+ [MEMINFO_ID_SWAP_FREE] = "SwapFree",
+ [MEMINFO_ID_DIRTY] = "Dirty",
+ [MEMINFO_ID_WRITEBACK] = "Writeback",
+ [MEMINFO_ID_ANON_PAGES] = "AnonPages",
+ [MEMINFO_ID_MAPPED] = "Mapped",
+ [MEMINFO_ID_SHMEM] = "Shmem",
+ [MEMINFO_ID_SLAB] = "Slab",
+ [MEMINFO_ID_SRECLAIMABLE] = "SReclaimable",
+ [MEMINFO_ID_SUNRECLAIM] = "SUnreclaim",
+ [MEMINFO_ID_KERNEL_STACK] = "KernelStack",
+ [MEMINFO_ID_PAGE_TABLES] = "PageTables",
+ [MEMINFO_ID_NFS_UNSTABLE] = "NFS_Unstable",
+ [MEMINFO_ID_BOUNCE] = "Bounce",
+ [MEMINFO_ID_WRITEBACK_TMP] = "WritebackTmp",
+ [MEMINFO_ID_COMMIT_LIMIT] = "CommitLimit",
+ [MEMINFO_ID_COMMITTED_AS] = "Committed_AS",
+ [MEMINFO_ID_VMALLOC_TOTAL] = "VmallocTotal",
+ [MEMINFO_ID_VMALLOC_USED] = "VmallocUsed",
+ [MEMINFO_ID_VMALLOC_CHUNK] = "VmallocChunk",
+};
+
+const char *meminfo_id_to_string(enum meminfo_id id) {
+ assert(id >= 0 && id < MEMINFO_ID_MAX);
+
+ return meminfo_string_lookup[id];
+}
+
+int proc_get_meminfo(struct meminfo *mi, enum meminfo_mask mask) {
+ _cleanup_fclose_ FILE *f = NULL;
+ enum meminfo_mask remain_mask = mask;
+ char buf[LINE_MAX];
+
+ assert(mi);
+
+ memset(mi, 0x0, sizeof(struct meminfo));
+
+ f = fopen("/proc/meminfo", "r");
+ if (!f)
+ return -errno;
+
+ if (remain_mask & MEMINFO_MASK_MEM_AVAILABLE)
+ remain_mask |= (MEMINFO_MASK_MEM_FREE |
+ MEMINFO_MASK_CACHED);
+
+ while (remain_mask) {
+ unsigned int v = 0;
+ enum meminfo_id id;
+ size_t l;
+
+ if (!fgets(buf, sizeof(buf), f)) {
+ if (ferror(f))
+ return -errno;
+ break;
+ }
+
+ l = strcspn(buf, ":");
+ if (!l)
+ break;
+
+ buf[l] = 0;
+
+ id = meminfo_string_to_id(buf);
+ if (id < 0 || id >= MEMINFO_ID_MAX)
+ continue;
+
+ if (!(remain_mask & (1ULL << id)))
+ continue;
+
+ remain_mask &= ~((1ULL << id));
+
+ if (sscanf(buf + l + 1, "%d", &v) != 1)
+ break;
+
+ mi->value[id] = v;
+ }
+
+ if (remain_mask & MEMINFO_MASK_MEM_AVAILABLE) {
+ mi->value[MEMINFO_ID_MEM_AVAILABLE] =
+ mi->value[MEMINFO_ID_MEM_FREE]
+ + mi->value[MEMINFO_ID_CACHED];
+ }
+
+ return 0;
+}
diff --git a/src/libsystem/proc.h b/src/libsystem/proc.h
index 132da3c..935db2d 100644
--- a/src/libsystem/proc.h
+++ b/src/libsystem/proc.h
@@ -228,6 +228,140 @@ enum smap_id smap_string_to_id(const char *str);
int proc_pid_get_smaps(pid_t pid, struct smaps **maps, enum smap_mask mask);
/**
+ * meminfo id
+ */
+enum meminfo_id {
+ MEMINFO_ID_INVALID = -1,
+ MEMINFO_ID_MEM_TOTAL = 0,
+ MEMINFO_ID_MEM_FREE,
+ MEMINFO_ID_MEM_AVAILABLE,
+ MEMINFO_ID_BUFFERS,
+ MEMINFO_ID_CACHED,
+ MEMINFO_ID_SWAP_CACHED,
+ MEMINFO_ID_ACTIVE,
+ MEMINFO_ID_INACTIVE,
+ MEMINFO_ID_ACTIVE_ANON,
+ MEMINFO_ID_INACTIVE_ANON,
+ MEMINFO_ID_ACTIVE_FILE,
+ MEMINFO_ID_INACTIVE_FILE,
+ MEMINFO_ID_UNEVICTABLE,
+ MEMINFO_ID_MLOCKED,
+ MEMINFO_ID_HIGH_TOTAL,
+ MEMINFO_ID_HIGH_FREE,
+ MEMINFO_ID_LOW_TOTAL,
+ MEMINFO_ID_LOW_FREE,
+ MEMINFO_ID_SWAP_TOTAL,
+ MEMINFO_ID_SWAP_FREE,
+ MEMINFO_ID_DIRTY,
+ MEMINFO_ID_WRITEBACK,
+ MEMINFO_ID_ANON_PAGES,
+ MEMINFO_ID_MAPPED,
+ MEMINFO_ID_SHMEM,
+ MEMINFO_ID_SLAB,
+ MEMINFO_ID_SRECLAIMABLE,
+ MEMINFO_ID_SUNRECLAIM,
+ MEMINFO_ID_KERNEL_STACK,
+ MEMINFO_ID_PAGE_TABLES,
+ MEMINFO_ID_NFS_UNSTABLE,
+ MEMINFO_ID_BOUNCE,
+ MEMINFO_ID_WRITEBACK_TMP,
+ MEMINFO_ID_COMMIT_LIMIT,
+ MEMINFO_ID_COMMITTED_AS,
+ MEMINFO_ID_VMALLOC_TOTAL,
+ MEMINFO_ID_VMALLOC_USED,
+ MEMINFO_ID_VMALLOC_CHUNK,
+ MEMINFO_ID_MAX,
+};
+
+/**
+ * meminfo mask
+ */
+enum meminfo_mask {
+ MEMINFO_MASK_MEM_TOTAL = 1ULL << MEMINFO_ID_MEM_TOTAL,
+ MEMINFO_MASK_MEM_FREE = 1ULL << MEMINFO_ID_MEM_FREE,
+ MEMINFO_MASK_MEM_AVAILABLE = 1ULL << MEMINFO_ID_MEM_AVAILABLE,
+ MEMINFO_MASK_BUFFERS = 1ULL << MEMINFO_ID_BUFFERS,
+ MEMINFO_MASK_CACHED = 1ULL << MEMINFO_ID_CACHED,
+ MEMINFO_MASK_SWAP_CACHED = 1ULL << MEMINFO_ID_SWAP_CACHED,
+ MEMINFO_MASK_ACTIVE = 1ULL << MEMINFO_ID_ACTIVE,
+ MEMINFO_MASK_INACTIVE = 1ULL << MEMINFO_ID_INACTIVE,
+ MEMINFO_MASK_ACTIVE_ANON = 1ULL << MEMINFO_ID_ACTIVE_ANON,
+ MEMINFO_MASK_INACTIVE_ANON = 1ULL << MEMINFO_ID_INACTIVE_ANON,
+ MEMINFO_MASK_ACTIVE_FILE = 1ULL << MEMINFO_ID_ACTIVE_FILE,
+ MEMINFO_MASK_INACTIVE_FILE = 1ULL << MEMINFO_ID_INACTIVE_FILE,
+ MEMINFO_MASK_UNEVICTABLE = 1ULL << MEMINFO_ID_UNEVICTABLE,
+ MEMINFO_MASK_MLOCKED = 1ULL << MEMINFO_ID_MLOCKED,
+ MEMINFO_MASK_HIGH_TOTAL = 1ULL << MEMINFO_ID_HIGH_TOTAL,
+ MEMINFO_MASK_HIGH_FREE = 1ULL << MEMINFO_ID_HIGH_FREE,
+ MEMINFO_MASK_LOW_TOTAL = 1ULL << MEMINFO_ID_LOW_TOTAL,
+ MEMINFO_MASK_LOW_FREE = 1ULL << MEMINFO_ID_LOW_FREE,
+ MEMINFO_MASK_SWAP_TOTAL = 1ULL << MEMINFO_ID_SWAP_TOTAL,
+ MEMINFO_MASK_SWAP_FREE = 1ULL << MEMINFO_ID_SWAP_FREE,
+ MEMINFO_MASK_DIRTY = 1ULL << MEMINFO_ID_DIRTY,
+ MEMINFO_MASK_WRITEBACK = 1ULL << MEMINFO_ID_WRITEBACK,
+ MEMINFO_MASK_ANON_PAGES = 1ULL << MEMINFO_ID_ANON_PAGES,
+ MEMINFO_MASK_MAPPED = 1ULL << MEMINFO_ID_MAPPED,
+ MEMINFO_MASK_SHMEM = 1ULL << MEMINFO_ID_SHMEM,
+ MEMINFO_MASK_SLAB = 1ULL << MEMINFO_ID_SLAB,
+ MEMINFO_MASK_SRECLAIMABLE = 1ULL << MEMINFO_ID_SRECLAIMABLE,
+ MEMINFO_MASK_SUNRECLAIM = 1ULL << MEMINFO_ID_SUNRECLAIM,
+ MEMINFO_MASK_KERNEL_STACK = 1ULL << MEMINFO_ID_KERNEL_STACK,
+ MEMINFO_MASK_PAGE_TABLES = 1ULL << MEMINFO_ID_PAGE_TABLES,
+ MEMINFO_MASK_NFS_UNSTABLE = 1ULL << MEMINFO_ID_NFS_UNSTABLE,
+ MEMINFO_MASK_BOUNCE = 1ULL << MEMINFO_ID_BOUNCE,
+ MEMINFO_MASK_WRITEBACK_TMP = 1ULL << MEMINFO_ID_WRITEBACK_TMP,
+ MEMINFO_MASK_COMMIT_LIMIT = 1ULL << MEMINFO_ID_COMMIT_LIMIT,
+ MEMINFO_MASK_COMMITTED_AS = 1ULL << MEMINFO_ID_COMMITTED_AS,
+ MEMINFO_MASK_VMALLOC_TOTAL = 1ULL << MEMINFO_ID_VMALLOC_TOTAL,
+ MEMINFO_MASK_VMALLOC_USED = 1ULL << MEMINFO_ID_VMALLOC_USED,
+ MEMINFO_MASK_VMALLOC_CHUNK = 1ULL << MEMINFO_ID_VMALLOC_CHUNK,
+ MEMINFO_MASK_ALL = (1ULL << MEMINFO_ID_MAX) - 1,
+};
+
+/**
+ * meminfo
+ */
+struct meminfo {
+ unsigned int value[MEMINFO_ID_MAX];
+};
+
+/**
+ * @brief Convert meminfo id to string
+ *
+ * @param id meminfo id
+ *
+ * @return converted string
+ */
+const char *meminfo_id_to_string(enum meminfo_id id);
+
+/**
+ * @brief Convert meminfo string to id
+ *
+ * @param str meminfo string
+ *
+ * @return converted id
+ */
+enum meminfo_id meminfo_string_to_id(const char *str);
+
+/**
+ * @brief Get system memory info(/proc/meminfo)
+ * @code{.c}
+ unsigned int get_mem_available(void)
+ {
+ struct meminfo mi;
+
+ proc_get_meminfo(&mi, MEMINFO_MASK_MEM_AVAILABLE);
+ }
+ * @endcode
+ *
+ * @param mi parsed meminfo struct.
+ * @param mask mask to get meminfo.
+ *
+ * @return 0 on success, -errno on failure.
+ */
+int proc_get_meminfo(struct meminfo *mi, enum meminfo_mask mask);
+
+/**
* @}
*/