summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Planeta <mcsim.planeta@gmail.com>2012-09-30 16:56:07 +0300
committerMaksym Planeta <mcsim.planeta@gmail.com>2012-09-30 16:56:07 +0300
commit32d4eb3d14fdb8f139675d3f8f779c42b49e3840 (patch)
tree58bab4a34043de1569d4a7fe0ec4bebd2d6ff9ea
parentaa3331b4e79f005a8e0d1fb7b46a186eee75568f (diff)
Add helper function pager_process_pages.
* libpager/pager.h (pager_process_pages): New function.
-rw-r--r--libpager/pager.h50
1 files changed, 50 insertions, 0 deletions
diff --git a/libpager/pager.h b/libpager/pager.h
index d8b38978..22e7a883 100644
--- a/libpager/pager.h
+++ b/libpager/pager.h
@@ -273,4 +273,54 @@ pager_memcpy (struct pager *pager, memory_object_t memobj,
off_t offset, void *other, size_t *size,
vm_prot_t prot);
+/* Inline function that helps process multiple blocks one by one, but
+ report about consecutive blocks with same status in one rpc call.
+ Function accept start page in START and number of pages in NPAGES.
+ Size of block is supplied via CHUNK_SIZE. PROCESS is function that
+ handles blocks, NO_ERROR_CODE and ERROR_CODE are functions that are
+ called to inform kernel about status of processed range */
+static inline void
+pager_process_pages(off_t start, off_t npages,
+ size_t chunk_size, error_t (*process)(off_t),
+ void (*no_error_code)(off_t, off_t),
+ void (*error_code)(error_t, off_t, off_t))
+{
+ error_t last_error = 0;
+ off_t range_start = start;
+ off_t range_len = 0;
+ error_t err = 0; /* Silent the warning */
+ while (range_start + range_len / vm_page_size < start + npages)
+ {
+ err = process (range_start * vm_page_size + range_len);
+ if (err != last_error)
+ {
+ if (!last_error)
+ {
+ if (range_len >= vm_page_size)
+ {
+ no_error_code (range_start, range_len);
+ range_start += range_len / vm_page_size;
+ range_len %= vm_page_size;
+ }
+ range_len += chunk_size;
+ }
+ else
+ {
+ error_code (err, range_start, range_len);
+ range_start += round_page (range_len) / vm_page_size;
+ range_len = 0;
+ }
+ last_error = err;
+ }
+ else
+ range_len += chunk_size;
+ }
+
+ range_len = round_page (range_len);
+ if (!err)
+ no_error_code (range_start, range_len);
+ else
+ error_code (err, range_start, range_len);
+}
+
#endif