diff options
author | WaLyong Cho <walyong.cho@samsung.com> | 2016-11-10 19:36:04 +0900 |
---|---|---|
committer | WaLyong Cho <walyong.cho@samsung.com> | 2016-11-10 20:13:21 +0900 |
commit | 35bf52f9d3823fad34a70c3c4fcbad9a50b8f8c1 (patch) | |
tree | 70b378be49f7c50b8061e319e86e277a556e757c | |
parent | 3856ef0845a510859ee0969b3839f659e43ab405 (diff) | |
download | libsystem-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.am | 3 | ||||
-rw-r--r-- | src/libsystem/.gitignore | 1 | ||||
-rw-r--r-- | src/libsystem/proc-meminfo-lookup.gperf | 67 | ||||
-rw-r--r-- | src/libsystem/proc.c | 105 | ||||
-rw-r--r-- | src/libsystem/proc.h | 134 |
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); + +/** * @} */ |