aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFengguang Wu <fengguang.wu@intel.com>2012-11-27 20:21:57 +0800
committerFengguang Wu <fengguang.wu@intel.com>2012-11-27 20:29:17 +0800
commit8ae9d69392eb4256170140642a8826f294bd40be (patch)
tree6510140f91840b89919df70c8b2e504a1ab088b6
parente9c1863693d43dac5f823dfe3352eed773d54586 (diff)
downloadvm-scalability-8ae9d69392eb4256170140642a8826f294bd40be.tar.gz
Abhinav's work on usemem_mbind.c
Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
-rw-r--r--usemem_mbind.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/usemem_mbind.c b/usemem_mbind.c
new file mode 100644
index 0000000..6e95549
--- /dev/null
+++ b/usemem_mbind.c
@@ -0,0 +1,157 @@
+/*
+ * moves pages across nodes using numactl
+ *
+ * source code provided by numactl source archive
+ *
+ * http://numactl.sourcearchive.com/documentation/2.0.5/files.html*
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <numa.h>
+#include <numaif.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+#include <errno.h>
+
+#define PAGES_TO_MOVE 1024
+
+unsigned int pagesize;
+unsigned int page_count = PAGES_TO_MOVE;
+
+char *page_base;
+void *pages;
+void *address;
+
+void **addr;
+int *status;
+int *nodes;
+int errors;
+int nr_nodes;
+
+struct bitmask *old_nodes;
+struct bitmask *new_nodes;
+
+void print_status(char *message, char *start_addr, int *status, unsigned long maxnode, int desired)
+{
+ int i = 0;
+
+ printf("%s\n", message);
+ printf("---------------------------------\n");
+
+ for (i = 0; i < page_count; i++) {
+ /* get page status for each page */
+ if (get_mempolicy(&status[i], NULL, maxnode,
+ (unsigned long *)(start_addr + (i * pagesize)),
+ MPOL_F_NODE|MPOL_F_ADDR) < 0) {
+ perror("move_pages");
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < page_count; i++) {
+ printf("Page %d vaddr=%p node=%d\n", i, pages + i * pagesize, status[i]);
+
+ if (((char *)pages)[ i* pagesize ] != (char) i) {
+ printf("*** Page content corrupted.\n");
+ errors++;
+ } else if (status[i] != desired) {
+ printf("Bad page state. Page %d status %d\n", i, status[i]);
+ exit(1);
+ }
+ }
+}
+
+void do_mbind(char *message, unsigned long *nodemask, unsigned long maxnode)
+{
+ printf("%s\n", message);
+
+ if (mbind(pages, page_count * pagesize, MPOL_BIND, nodemask,
+ maxnode, MPOL_MF_MOVE | MPOL_MF_STRICT) < 0) {
+ perror("mbind");
+ errors++;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ pagesize = getpagesize();
+
+ /* probe number of nodes on the system */
+ nr_nodes = numa_max_node()+1;
+
+ old_nodes = numa_bitmask_alloc(nr_nodes);
+ new_nodes = numa_bitmask_alloc(nr_nodes);
+
+ numa_bitmask_setbit(old_nodes, 0);
+ numa_bitmask_setbit(new_nodes, 1);
+
+ /* check if atleast 2 nodes available */
+ if (nr_nodes < 2) {
+ printf("A minimum of 2 nodes is required for this test.\n");
+ exit(1);
+ }
+
+ /* check if no. of pages is provided as an argument */
+ setbuf(stdout, NULL);
+ printf("\n");
+ printf("******* mbind migration test *******\n");
+ if (argc > 1)
+ sscanf(argv[1], "%d", &page_count);
+
+ /* Allocate address for variables */
+ page_base = malloc((pagesize + 1) * page_count);
+ addr = malloc(sizeof(char *) * page_count);
+ status = malloc(sizeof(int *) * page_count);
+ nodes = malloc(sizeof(int *) * page_count);
+ if (!page_base || !addr || !status || !nodes) {
+ printf("Unable to allocate memory\n");
+ exit(1);
+ }
+
+ /* align page boundaries */
+ posix_memalign(&pages, pagesize, page_count * pagesize);
+
+ /* initialize variables */
+ for (i = 0; i < page_count; i++) {
+ ((char *)pages)[ i * pagesize ] = (char) i;
+ addr[i] = pages + i * pagesize;
+ nodes[i] = 0;
+ status[i] = -123;
+ }
+
+
+ /* Move pages to node zero */
+ if (numa_move_pages(0, page_count, addr, nodes, status, 0) < 0) {
+ perror("Error moving pages to node 0\n");
+ exit(1);
+ }
+
+ /* bind pages to node 0 */
+ do_mbind("Moving pages via mbind to node 0 ...", old_nodes->maskp, old_nodes->size + 1);
+
+ /* print page status before binding to node 1 */
+ print_status("Page status before binding to node 1", pages, status, old_nodes->size + 1, 0);
+
+
+ /* bind pages to node 1*/
+ do_mbind("Moving pages via mbind from node 0 to 1 ...", new_nodes->maskp, new_nodes->size + 1);
+
+ /* print page status after binding to node 1*/
+ print_status("Page status after binding to node 1", pages, status, new_nodes->size + 1, 1);
+
+ /* Free malloc'd memory */
+ free(page_base);
+ free(addr);
+ free(nodes);
+ free(status);
+
+ if (!errors)
+ printf("Test successful.\n");
+ else
+ printf("%d errors.\n", errors);
+
+ return errors > 0 ? 1 : 0;
+}