create_same_memory() was too large and had lots of duplicated codes,
and it's a little hard-coding, so that it's not easy to read and
extend it.

I splited it for five sub-functions:

  _ksm_child_memset();
  _create_ksm_child();
  _stop_ksm_children();
  _resume_ksm_children();
  create_smae_memory();

Also I intruduced a data struct to control the mergeable data:

  struct _ksm_merge_data {
        char data;
        int mergeable_size;
  };

Signed-off-by: Zhouping Liu <[email protected]>
---
 testcases/kernel/mem/include/_private.h |   2 +-
 testcases/kernel/mem/lib/mem.c          | 425 +++++++++++++-------------------
 2 files changed, 170 insertions(+), 257 deletions(-)

diff --git a/testcases/kernel/mem/include/_private.h 
b/testcases/kernel/mem/include/_private.h
index 71164f5..43eda0e 100644
--- a/testcases/kernel/mem/include/_private.h
+++ b/testcases/kernel/mem/include/_private.h
@@ -11,7 +11,7 @@ static void _check(char *path, long int value);
 static void _group_check(int run, int pages_shared, int pages_sharing,
                int pages_volatile, int pages_unshared,
                int sleep_millisecs, int pages_to_scan);
-static void _verify(char value, int proc, int start, int end,
+static void _verify(char **memory_new, char value, int proc, int start, int 
end,
                int start2, int end2);
 
 /* cpuset/memcg */
diff --git a/testcases/kernel/mem/lib/mem.c b/testcases/kernel/mem/lib/mem.c
index f095fe1..05abcc7 100644
--- a/testcases/kernel/mem/lib/mem.c
+++ b/testcases/kernel/mem/lib/mem.c
@@ -200,8 +200,8 @@ static void _group_check(int run, int pages_shared, int 
pages_sharing,
        _check("pages_to_scan", pages_to_scan);
 }
 
-static void _verify(char value, int proc, int start, int end,
-                   int start2, int end2)
+static void _verify(char **memory_new, char value, int proc,
+                   int start, int end, int start2, int end2)
 {
        int i, j;
        void *s = NULL;
@@ -212,14 +212,14 @@ static void _verify(char value, int proc, int start, int 
end,
 
        tst_resm(TINFO, "child %d verifies memory content.", proc);
        memset(s, value, (end - start) * (end2 - start2));
-       if (memcmp(memory[proc][start], s, (end - start) * (end2 - start2))
+       if (memcmp(memory_new[start], s, (end - start) * (end2 - start2))
            != 0)
                for (j = start; j < end; j++)
                        for (i = start2; i < end2; i++)
-                               if (memory[proc][j][i] != value)
+                               if (memory_new[j][i] != value)
                                        tst_resm(TFAIL, "child %d has %c at "
                                                 "%d,%d,%d.",
-                                                proc, memory[proc][j][i], proc,
+                                                proc, memory_new[j][i], proc,
                                                 j, i);
        free(s);
 }
@@ -235,299 +235,212 @@ void write_memcg(void)
        write_file(MEMCG_PATH_NEW "/tasks", buf);
 }
 
-void create_same_memory(int size, int num, int unit)
+struct _ksm_merge_data {
+       char data;
+       int mergeable_size;
+};
+
+void _ksm_child_memset(int child_num, int size, int total_unit,
+                struct _ksm_merge_data ksm_merge_data, char **memory_new)
 {
-       char buf[BUFSIZ];
-       int i, j, k;
-       int status;
-       int *child;
-       long ps, pages;
+       int i, j;
+       int unit = size / total_unit;
 
-       ps = sysconf(_SC_PAGE_SIZE);
-       pages = 1024 * 1024 / ps;
+       tst_resm(TINFO, "child %d continues...", child_num);
 
-       child = malloc(num);
-       if (child == NULL)
-               tst_brkm(TBROK | TERRNO, cleanup, "malloc");
+       if (ksm_merge_data.mergeable_size == size * MB) {
+               tst_resm(TINFO, "child %d allocates %d MB filled with '%c'",
+                       child_num, size, ksm_merge_data.data);
 
-       memory = malloc(num * sizeof(**memory));
-       if (memory == NULL)
-               tst_brkm(TBROK | TERRNO, cleanup, "malloc");
+       } else {
+               tst_resm(TINFO, "child %d allocates %d MB filled with '%c'"
+                               " except one page with 'e'",
+                               child_num, size, ksm_merge_data.data);
+       }
 
-       /* Don't call cleanup in those children. Instead, do a cleanup from the
-          parent after fetched children's status. */
-       switch (child[0] = fork()) {
-       case -1:
-               tst_brkm(TBROK | TERRNO, cleanup, "fork");
-       case 0:
-               tst_resm(TINFO, "child 0 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-
-               tst_resm(TINFO, "child 0 continues...");
-               tst_resm(TINFO, "child 0 allocates %d MB filled with 'c'.",
-                        size);
-               memory[0] = malloc(size / unit * sizeof(*memory));
-               if (memory[0] == NULL)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "malloc");
-               for (j = 0; j * unit < size; j++) {
-                       memory[0][j] = mmap(NULL, unit * MB,
-                                           PROT_READ | PROT_WRITE,
-                                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-                       if (memory[0][j] == MAP_FAILED)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "mmap");
+       for (j = 0; j < total_unit; j++) {
+               for (i = 0; i < unit * MB; i++)
+                       memory_new[j][i] = ksm_merge_data.data;
+       }
+
+       /* if it contains unshared page, then set 'e' char
+        * at the end of the last page
+        */
+       if (ksm_merge_data.mergeable_size < size * MB)
+               memory_new[j-1][i-1] = 'e';
+}
 
+void _create_ksm_child(int child_num, int size, int unit,
+                      struct _ksm_merge_data *ksm_merge_data)
+{
+       int j, total_unit;
+       char **memory_new;
+
+       /* The total units in all */
+       total_unit = size / unit;
+
+       /* Apply for the space for memory_new */
+       memory_new = (char **)malloc(total_unit * sizeof(char *));
+       for (j = 0; j < total_unit; j++) {
+               memory_new[j] = mmap(NULL, unit * MB, PROT_READ|PROT_WRITE,
+                       MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+               if (memory_new[j] == MAP_FAILED)
+                       tst_brkm(TBROK|TERRNO, tst_exit, "mmap");
 #ifdef HAVE_MADV_MERGEABLE
-                       if (madvise(memory[0][j], unit * MB, MADV_MERGEABLE)
-                           == -1)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "madvise");
+               if (madvise(memory_new[j], unit * MB, MADV_MERGEABLE) == -1)
+                       tst_brkm(TBROK|TERRNO, tst_exit, "madvise");
 #endif
-                       for (i = 0; i < unit * MB; i++)
-                               memory[0][j][i] = 'c';
-               }
-               tst_resm(TINFO, "child 0 stops.");
+       }
+
+       tst_resm(TINFO, "child %d stops.", child_num);
+       if (raise(SIGSTOP) == -1)
+               tst_brkm(TBROK|TERRNO, tst_exit, "kill");
+       fflush(stdout);
+
+       for (j = 0; j < 4; j++) {
+
+               _ksm_child_memset(child_num, size, total_unit,
+                                 ksm_merge_data[j], memory_new);
+
+               fflush(stdout);
+
+               tst_resm(TINFO, "child %d stops.", child_num);
                if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-
-               tst_resm(TINFO, "child 0 continues...");
-               _verify('c', 0, 0, size / unit, 0, unit * MB);
-               tst_resm(TINFO, "child 0 changes memory content to 'd'.");
-               for (j = 0; j < size / unit; j++) {
-                       for (i = 0; i < unit * MB; i++)
-                               memory[0][j][i] = 'd';
+                       tst_brkm(TBROK|TERRNO, tst_exit, "kill");
+
+               if (ksm_merge_data[j].mergeable_size < size * MB) {
+                       _verify(memory_new, 'e', child_num, total_unit - 1,
+                               total_unit, unit * MB - 1, unit * MB);
+                       _verify(memory_new, ksm_merge_data[j].data, child_num,
+                               0, total_unit, 0, unit * MB - 1);
+               } else {
+                       _verify(memory_new, ksm_merge_data[j].data, child_num,
+                               0, total_unit, 0, unit * MB);
                }
-               /* Unmerge. */
-               tst_resm(TINFO, "child 0 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
+       }
 
-               tst_resm(TINFO, "child 0 continues...");
-               _verify('d', 0, 0, size / unit, 0, unit * MB);
-               /* Stop. */
-               tst_resm(TINFO, "child 0 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-               tst_resm(TINFO, "child 0 continues...");
-               exit(0);
+       tst_resm(TINFO, "child %d finished.", child_num);
+}
+
+void _stop_ksm_children(int *child, int num)
+{
+       int k, status;
+
+       tst_resm(TINFO, "wait for all children to stop.");
+       for (k = 0; k < num; k++) {
+               if (waitpid(child[k], &status, WUNTRACED) == -1)
+                       tst_brkm(TBROK|TERRNO, cleanup, "waitpid");
+               if (!WIFSTOPPED(status))
+                       tst_brkm(TBROK, cleanup, "child %d was not stopped", k);
        }
-       switch (child[1] = fork()) {
-       case -1:
-               tst_brkm(TBROK | TERRNO, cleanup, "fork");
-       case 0:
-               tst_resm(TINFO, "child 1 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-               tst_resm(TINFO, "child 1 continues...");
-               tst_resm(TINFO, "child 1 allocates %d MB filled with 'a'.",
-                        size);
-               memory[1] = malloc(size / unit * sizeof(*memory));
-               if (memory[1] == NULL)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "malloc");
-               for (j = 0; j < size / unit; j++) {
-                       memory[1][j] = mmap(NULL, unit * MB,
-                                           PROT_READ | PROT_WRITE,
-                                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-                       if (memory[1][j] == MAP_FAILED)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "mmap");
-#ifdef HAVE_MADV_MERGEABLE
-                       if (madvise(memory[1][j], unit * MB, MADV_MERGEABLE)
-                           == -1)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "madvise");
-#endif
-                       for (i = 0; i < unit * MB; i++)
-                               memory[1][j][i] = 'a';
-               }
-               tst_resm(TINFO, "child 1 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-               tst_resm(TINFO, "child 1 continues...");
-               _verify('a', 1, 0, size / unit, 0, unit * MB);
-               tst_resm(TINFO, "child 1 changes memory content to 'b'.");
-               for (j = 0; j < size / unit; j++) {
-                       for (i = 0; i < unit * MB; i++)
-                               memory[1][j][i] = 'b';
-               }
-               tst_resm(TINFO, "child 1 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-               tst_resm(TINFO, "child 1 continues...");
-               _verify('b', 1, 0, size / unit, 0, unit * MB);
-               tst_resm(TINFO, "child 1 changes memory content to 'd'");
-               for (j = 0; j < size / unit; j++) {
-                       for (i = 0; i < unit * MB; i++)
-                               memory[1][j][i] = 'd';
-               }
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
+}
 
-               tst_resm(TINFO, "child 1 continues...");
-               _verify('d', 1, 0, size / unit, 0, unit * MB);
-               tst_resm(TINFO, "child 1 changes one page to 'e'.");
-               memory[1][size / unit - 1][unit * MB - 1] = 'e';
+void _resume_ksm_children(int *child, int num)
+{
+       int k, status;
 
-               /* Unmerge. */
-               tst_resm(TINFO, "child 1 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-               tst_resm(TINFO, "child 1 continues...");
-               _verify('e', 1, size / unit - 1, size / unit,
-                       unit * MB - 1, unit * MB);
-               _verify('d', 1, 0, size / unit - 1, 0, unit * MB - 1);
-
-               /* Stop. */
-               tst_resm(TINFO, "child 1 stops.");
-               if (raise(SIGSTOP) == -1)
-                       tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-               tst_resm(TINFO, "child 1 continues...");
-               exit(0);
+       tst_resm(TINFO, "resume all children.");
+       for (k = 0; k < num; k++) {
+               if (kill(child[k], SIGCONT) == -1)
+                       tst_brkm(TBROK|TERRNO, cleanup, "kill child[%d]", k);
        }
-       for (k = 2; k < num; k++) {
-               switch (child[k] = fork()) {
+       fflush(stdout);
+}
+
+void create_same_memory(int size, int num, int unit)
+{
+       char buf[BUFSIZ];
+       int i, j, status, *child;
+       unsigned long ps, pages;
+       struct _ksm_merge_data **ksm_data;
+
+       struct _ksm_merge_data ksm_data0[] = {
+              {'c', size*MB}, {'c', size*MB}, {'d', size*MB}, {'d', size*MB},
+       };
+       struct _ksm_merge_data ksm_data1[] = {
+              {'a', size*MB}, {'b', size*MB}, {'d', size*MB}, {'d', size*MB-1},
+       };
+       struct _ksm_merge_data ksm_data2[] = {
+              {'a', size*MB}, {'a', size*MB}, {'d', size*MB}, {'d', size*MB},
+       };
+
+       ps = sysconf(_SC_PAGE_SIZE);
+       pages = MB / ps;
+
+       ksm_data = (struct _ksm_merge_data **)malloc
+                  ((num - 3) * sizeof(struct _ksm_merge_data *));
+       /* Since from third child, the data is same with the first child's */
+       for (i = 0; i < num - 3; i++) {
+               ksm_data[i] = (struct _ksm_merge_data *)malloc
+                             (4 * sizeof(struct _ksm_merge_data));
+               for (j = 0; j < 4; j++) {
+                       ksm_data[i][j].data = ksm_data0[j].data;
+                       ksm_data[i][j].mergeable_size =
+                               ksm_data0[j].mergeable_size;
+               }
+       }
+
+       child = (int *)malloc(num * sizeof(int));
+       if (child == NULL)
+               tst_brkm(TBROK | TERRNO, cleanup, "malloc");
+
+       for (i = 0; i < num; i++) {
+               fflush(stdout);
+               switch (child[i] = fork()) {
                case -1:
-                       tst_brkm(TBROK | TERRNO, cleanup, "fork");
+                       tst_brkm(TBROK|TERRNO, cleanup, "fork");
                case 0:
-                       tst_resm(TINFO, "child %d stops.", k);
-                       if (raise(SIGSTOP) == -1)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-                       tst_resm(TINFO, "child %d continues...", k);
-                       tst_resm(TINFO, "child %d allocates %d "
-                                "MB filled with 'a'.", k, size);
-                       memory[k] = malloc(size / unit * sizeof(*memory));
-                       if (memory[k] == NULL)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "malloc");
-                       for (j = 0; j < size / unit; j++) {
-                               memory[k][j] = mmap(NULL, unit * MB,
-                                                   PROT_READ | PROT_WRITE,
-                                                   MAP_ANONYMOUS
-                                                   | MAP_PRIVATE, -1, 0);
-                               if (memory[k][j] == MAP_FAILED)
-                                       tst_brkm(TBROK | TERRNO, cleanup,
-                                                "mmap");
-#ifdef HAVE_MADV_MERGEABLE
-                               if (madvise(memory[k][j], unit * MB,
-                                           MADV_MERGEABLE) == -1)
-                                       tst_brkm(TBROK | TERRNO, cleanup,
-                                                "madvise");
-#endif
-                               for (i = 0; i < unit * MB; i++)
-                                       memory[k][j][i] = 'a';
+                       if (i == 0) {
+                               _create_ksm_child(i, size, unit, ksm_data0);
+                               exit(0);
+                       } else if (i == 1) {
+                               _create_ksm_child(i, size, unit, ksm_data1);
+                               exit(0);
+                       } else if (i == 2) {
+                               _create_ksm_child(i, size, unit, ksm_data2);
+                               exit(0);
+                       } else {
+                               _create_ksm_child(i, size, unit, ksm_data[i-3]);
+                               exit(0);
                        }
-                       tst_resm(TINFO, "child %d stops.", k);
-                       if (raise(SIGSTOP) == -1)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-                       tst_resm(TINFO, "child %d continues...", k);
-                       tst_resm(TINFO, "child %d changes memory content to "
-                                "'d'", k);
-                       for (j = 0; j < size / unit; j++) {
-                               for (i = 0; i < unit * MB; i++)
-                                       memory[k][j][i] = 'd';
-                       }
-                       /* Unmerge. */
-                       tst_resm(TINFO, "child %d stops.", k);
-                       if (raise(SIGSTOP) == -1)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-                       tst_resm(TINFO, "child %d continues...", k);
-
-                       /* Stop. */
-                       tst_resm(TINFO, "child %d stops.", k);
-                       if (raise(SIGSTOP) == -1)
-                               tst_brkm(TBROK | TERRNO, tst_exit, "kill");
-                       tst_resm(TINFO, "child %d continues...", k);
-                       exit(0);
                }
        }
+
+       _stop_ksm_children(child, num);
+
        tst_resm(TINFO, "KSM merging...");
        write_file(PATH_KSM "run", "1");
        snprintf(buf, BUFSIZ, "%ld", size * pages * num);
        write_file(PATH_KSM "pages_to_scan", buf);
        write_file(PATH_KSM "sleep_millisecs", "0");
 
-       tst_resm(TINFO, "wait for all children to stop.");
-       for (k = 0; k < num; k++) {
-               if (waitpid(child[k], &status, WUNTRACED) == -1)
-                       tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
-               if (!WIFSTOPPED(status))
-                       tst_brkm(TBROK, cleanup, "child %d was not stopped.",
-                                k);
-       }
-       tst_resm(TINFO, "resume all children.");
-       for (k = 0; k < num; k++) {
-               if (kill(child[k], SIGCONT) == -1)
-                       tst_brkm(TBROK | TERRNO, cleanup, "kill child[%d]", k);
-       }
+       _resume_ksm_children(child, num);
        _group_check(1, 2, size * num * pages - 2, 0, 0, 0, size * pages * num);
 
-       tst_resm(TINFO, "wait for child 1 to stop.");
-       if (waitpid(child[1], &status, WUNTRACED) == -1)
-               tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
-       if (!WIFSTOPPED(status))
-               tst_brkm(TBROK, cleanup, "child 1 was not stopped.");
-
-       /* Child 1 changes all pages to 'b'. */
-       tst_resm(TINFO, "resume child 1.");
-       if (kill(child[1], SIGCONT) == -1)
-               tst_brkm(TBROK | TERRNO, cleanup, "kill");
+       _stop_ksm_children(child, num);
+       _resume_ksm_children(child, num);
        _group_check(1, 3, size * num * pages - 3, 0, 0, 0, size * pages * num);
 
-       tst_resm(TINFO, "wait for child 1 to stop.");
-       if (waitpid(child[1], &status, WUNTRACED) == -1)
-               tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
-       if (!WIFSTOPPED(status))
-               tst_brkm(TBROK, cleanup, "child 1 was not stopped.");
-
-       /* All children change pages to 'd'. */
-       tst_resm(TINFO, "resume all children.");
-       for (k = 0; k < num; k++) {
-               if (kill(child[k], SIGCONT) == -1)
-                       tst_brkm(TBROK | TERRNO, cleanup, "kill child[%d]", k);
-       }
+       _stop_ksm_children(child, num);
+       _resume_ksm_children(child, num);
        _group_check(1, 1, size * num * pages - 1, 0, 0, 0, size * pages * num);
 
-       tst_resm(TINFO, "wait for all children to stop.");
-       for (k = 0; k < num; k++) {
-               if (waitpid(child[k], &status, WUNTRACED) == -1)
-                       tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
-               if (!WIFSTOPPED(status))
-                       tst_brkm(TBROK, cleanup, "child %d was not stopped.",
-                                k);
-       }
-       /* Child 1 changes pages to 'e'. */
-       tst_resm(TINFO, "resume child 1.");
-       if (kill(child[1], SIGCONT) == -1)
-               tst_brkm(TBROK | TERRNO, cleanup, "kill");
+       _stop_ksm_children(child, num);
+       _resume_ksm_children(child, num);
        _group_check(1, 1, size * num * pages - 2, 0, 1, 0, size * pages * num);
 
-       tst_resm(TINFO, "wait for child 1 to stop.");
-       if (waitpid(child[1], &status, WUNTRACED) == -1)
-               tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
-       if (!WIFSTOPPED(status))
-               tst_brkm(TBROK, cleanup, "child 1 was not stopped.");
+       _stop_ksm_children(child, num);
 
-       tst_resm(TINFO, "resume all children.");
-       for (k = 0; k < num; k++) {
-               if (kill(child[k], SIGCONT) == -1)
-                       tst_brkm(TBROK | TERRNO, cleanup, "kill child[%d]", k);
-       }
        tst_resm(TINFO, "KSM unmerging...");
        write_file(PATH_KSM "run", "2");
+
+       _resume_ksm_children(child, num);
        _group_check(2, 0, 0, 0, 0, 0, size * pages * num);
 
-       tst_resm(TINFO, "wait for all children to stop.");
-       for (k = 0; k < num; k++) {
-               if (waitpid(child[k], &status, WUNTRACED) == -1)
-                       tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
-               if (!WIFSTOPPED(status))
-                       tst_brkm(TBROK, cleanup, "child %d was not stopped.",
-                                k);
-       }
-       tst_resm(TINFO, "resume all children.");
-       for (k = 0; k < num; k++) {
-               if (kill(child[k], SIGCONT) == -1)
-                       tst_brkm(TBROK | TERRNO, cleanup, "kill child[%d]", k);
-       }
        tst_resm(TINFO, "stop KSM.");
        write_file(PATH_KSM "run", "0");
        _group_check(0, 0, 0, 0, 0, 0, size * pages * num);
+
        while (waitpid(-1, &status, WUNTRACED | WCONTINUED) > 0)
                if (WEXITSTATUS(status) != 0)
                        tst_resm(TFAIL, "child exit status is %d",
-- 
1.7.11.7


------------------------------------------------------------------------------
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. SALE $99.99 this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122412
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to