diff options
author | Sandeep Patil <sspatil@google.com> | 2018-08-15 13:24:09 -0700 |
---|---|---|
committer | Sandeep Patil <sspatil@google.com> | 2018-08-22 16:59:20 -0700 |
commit | ac5018d57c032195ac15b02043c33b057417d544 (patch) | |
tree | 140afce7c49d81779e8f2349dd608e260564eba3 /libpagemap/pm_process.c | |
parent | 1ac3fe7ad956e2d07d3334fc6f53721880cbd319 (diff) | |
download | extras-ac5018d57c032195ac15b02043c33b057417d544.tar.gz |
libpagemap: Add APIs to mark and read idle pages of a process.
pm_kernel_init_page_idle() - Initialize idle page tracking.
pm_kernel_has_page_idle() - Returns 1 if idle page tracking has been
successfully initialized.
pm_kernel_get_page_idle() - Gets the idle status of the page frame.
pm_kernel_mark_page_idle() - Marks one or many page frames idle.
pm_kernel_page_is_accessed() - Returns 1 if page is accessed.
pm_map_mark_idle() - Marks mapped pages from a pagemap idle.
Added '-i' usage flag to procmem that tells procmem to use idle page
tracking. The flag is ignored in the absense of '-w' or '-W' options.
Bug: 111694435
Test: procmem -i -h 1
Test: procmem -h -W 1 && procmem -h -w 1
Test: procmem -h -i -W 1 && procmem -h -i -w 1
Change-Id: Ib9cb679427798426c9477500552e9aa83a40fd48
Signed-off-by: Sandeep Patil <sspatil@google.com>
Diffstat (limited to 'libpagemap/pm_process.c')
-rw-r--r-- | libpagemap/pm_process.c | 80 |
1 files changed, 58 insertions, 22 deletions
diff --git a/libpagemap/pm_process.c b/libpagemap/pm_process.c index 5d47e26c..98c1c6a0 100644 --- a/libpagemap/pm_process.c +++ b/libpagemap/pm_process.c @@ -27,6 +27,8 @@ #include "pm_map.h" static int read_maps(pm_process_t *proc); +static int pm_process_clear_refs(pm_process_t* proc); +static int pm_process_mark_idle(pm_process_t* proc); #define MAX_FILENAME 64 @@ -113,8 +115,9 @@ int pm_process_pagemap_range(pm_process_t *proc, off64_t off; int error; - if (!proc || (low > high) || !range_out || !len) - return -1; + if (!proc || (low > high) || !range_out || !len) { + return -EINVAL; + } if (low == high) { *range_out = NULL; @@ -126,12 +129,13 @@ int pm_process_pagemap_range(pm_process_t *proc, numpages = (high - low) / proc->ker->pagesize; range = malloc(numpages * sizeof(uint64_t)); - if (!range) - return errno; + if (!range) { + return -ENOMEM; + } off = lseek64(proc->pagemap_fd, firstpage * sizeof(uint64_t), SEEK_SET); if (off == (off_t)-1) { - error = errno; + error = -errno; free(range); return error; } @@ -143,7 +147,7 @@ int pm_process_pagemap_range(pm_process_t *proc, *range_out = NULL; return 0; } else if (error < 0 || (error > 0 && error < (int)(numpages * sizeof(uint64_t)))) { - error = (error < 0) ? errno : -1; + error = (error < 0) ? -errno : -EIO; free(range); return error; } @@ -179,8 +183,6 @@ int pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len) { int pm_process_workingset(pm_process_t *proc, pm_memusage_t *ws_out, int reset) { pm_memusage_t ws, map_ws; - char filename[MAX_FILENAME]; - int fd; int i; int error; @@ -200,24 +202,12 @@ int pm_process_workingset(pm_process_t *proc, pm_memusage_add(&ws, &map_ws); } - memcpy(ws_out, &ws, sizeof(ws)); } if (reset) { - error = snprintf(filename, MAX_FILENAME, "/proc/%d/clear_refs", - proc->pid); - if (error < 0 || error >= MAX_FILENAME) { - return (error < 0) ? (errno) : (-1); - } - - fd = open(filename, O_WRONLY); - if (fd < 0) - return errno; - - write(fd, "1\n", strlen("1\n")); - - close(fd); + return pm_kernel_has_page_idle(proc->ker) ? pm_process_mark_idle(proc) + : pm_process_clear_refs(proc); } return 0; @@ -329,3 +319,49 @@ static int read_maps(pm_process_t *proc) { return 0; } + +static int pm_process_clear_refs(pm_process_t* proc) { + int error; + char filename[MAX_FILENAME]; + + if (!proc) { + return -EINVAL; + } + + error = snprintf(filename, MAX_FILENAME, "/proc/%d/clear_refs", proc->pid); + if (error < 0 || error >= MAX_FILENAME) { + return (error < 0) ? -errno : -1; + } + + int fd = open(filename, O_WRONLY | O_CLOEXEC); + if (fd < 0) { + return -errno; + } + + const char* cmd = "1\n"; + size_t cmdlen = strlen(cmd); + + error = TEMP_FAILURE_RETRY(write(fd, cmd, cmdlen)); + error = (error == cmdlen) ? 0 : -errno; + + close(fd); + + return error; +} + +static int pm_process_mark_idle(pm_process_t* proc) { + int error; + + if (!proc) { + return -EINVAL; + } + + for (int i = 0; i < proc->num_maps; i++) { + error = pm_map_mark_idle(proc->maps[i]); + if (error) { + return error; + } + } + + return 0; +} |