summaryrefslogtreecommitdiff
path: root/libpagemap/pm_process.c
diff options
context:
space:
mode:
authorSandeep Patil <sspatil@google.com>2018-08-15 13:24:09 -0700
committerSandeep Patil <sspatil@google.com>2018-08-22 16:59:20 -0700
commitac5018d57c032195ac15b02043c33b057417d544 (patch)
tree140afce7c49d81779e8f2349dd608e260564eba3 /libpagemap/pm_process.c
parent1ac3fe7ad956e2d07d3334fc6f53721880cbd319 (diff)
downloadextras-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.c80
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;
+}