This test case currently fails with following errors in dmesg:
Looks like the VM_NORESERVE flag on some maps triggers the error
(CKPT_VMA_NOT_SUPPORTED includes the VM_NORESERVE flag)

        [4999:4999:c/r:checkpoint_vmas:625] vma 0xb7200000-0xb7221000 flags
        0x200073
        [err -38][pos 102940][E @ checkpoint_vmas:629][pid 4976 tsk pthread2]
        vma: bad flags (0x200073)
        [4999:4999:c/r:checkpoint_task_objs:264] mm: objref -38
        [4999:4999:c/r:ckpt_write_obj_type:66] type 9999 len 8
        [4999:4999:c/r:ckpt_write_obj_type:66] type 5 len 93
        [err -38][pos 102940][E @ checkpoint_task_objs:266][pid 4976 tsk
        pthread2]mm_struct
        [4999:4999:c/r:checkpoint_task:450] objs -38
        [4999:4999:c/r:pgarr_release_pages:101] total pages 0
---

From: Sukadev Bhattiprolu <[email protected]>
Date: Sat, 26 Dec 2009 13:08:32 +0530
Subject: [PATCH 1/3] pthread2: Test additional pthread attributes

Extend the test case to test all (most) pthread attributes in a single
test.

Signed-off-by: Sukadev Bhattiprolu <[email protected]>
---
 process-tree/pthread2.c      |  400 +++++++++++++++++++++++++++++++++++++-----
 process-tree/run-pthread2.sh |    5 +-
 2 files changed, 355 insertions(+), 50 deletions(-)

diff --git a/process-tree/pthread2.c b/process-tree/pthread2.c
index 6ac1e52..a773245 100644
--- a/process-tree/pthread2.c
+++ b/process-tree/pthread2.c
@@ -12,11 +12,10 @@
 #define LOG_PREFIX     "logs.d/pthread2"
 
 FILE *logfp;
-
 int num_threads = 8;
-void **exp_addrs;
-size_t  *exp_sizes;
 int *tstatus;
+pthread_barrier_t barrier;
+pthread_mutex_t dump_lock;
 
 static void usage(char *argv[])
 {
@@ -25,19 +24,10 @@ static void usage(char *argv[])
        do_exit(1);
 }
 
-pthread_attr_t *get_thread_attr(int tnum)
+pthread_attr_t *alloc_thread_attr()
 {
-       int rc, size;
+       int rc;
        pthread_attr_t *attr;
-       void *stack;
-
-       size = MIN_STACK_SIZE + (tnum * getpagesize());
-
-       stack = malloc(size);
-       if (!stack) {
-               fprintf(logfp, "malloc(stack): error %s\n", strerror(errno));
-               do_exit(1);
-       }
 
        attr = malloc(sizeof(pthread_attr_t));
        if (!attr) {
@@ -52,29 +42,211 @@ pthread_attr_t *get_thread_attr(int tnum)
                do_exit(1);
        }
 
-       rc = pthread_attr_setstack(attr, stack, size);
+       return attr;
+}
+
+#ifndef debug
+dump_attr(char *msg, pthread_attr_t *attr)
+{
+}
+#endif
+
+get_affinity(int tnum, pthread_attr_t *attr, cpu_set_t *cpu_set)
+{
+       int rc;
+
+       fprintf(logfp, "sizeof(cpu_set_t) %d\n", sizeof(cpu_set_t));
+
+       rc = pthread_attr_getaffinity_np(attr, sizeof(cpu_set_t), cpu_set);
        if (rc < 0) {
-               fprintf(logfp, "pthread_attr_setstack(): rc %d error %s\n",
-                               rc, strerror(errno));
+               fprintf(logfp, "pthread_attr_getaffin() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
                do_exit(1);
        }
 
-       return attr;
 }
 
-int get_stack_info(pthread_t tid, void **addrp, size_t *sizep)
+compare_affinity(int tnum, pthread_attr_t *exp_attr, pthread_attr_t *act_attr)
+{
+       cpu_set_t exp_cpus, act_cpus;
+
+       get_affinity(tnum, exp_attr, &exp_cpus);
+       get_affinity(tnum, act_attr, &act_cpus);
+
+       if (memcmp(&exp_cpus, &act_cpus, sizeof(cpu_set_t))) {
+               fprintf(logfp, "cpu set mismatch\n");
+               do_exit(1);
+       }
+}
+
+get_detachstate(int tnum, pthread_attr_t *attr, int *state)
 {
        int rc;
-       pthread_attr_t attr;
 
-       rc = pthread_getattr_np(tid, &attr);
+       rc = pthread_attr_getdetachstate(attr, state);
        if (rc < 0) {
-               fprintf(logfp, "pthread_getattr_np failed, rc %d, %s\n", rc,
-                               strerror(errno));
-               pthread_exit(ERROR_EXIT);
+               fprintf(logfp, "pthread_attr_getdetachstate() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+}
+
+compare_detachstate(int tnum, pthread_attr_t *exp_attr,
+               pthread_attr_t *act_attr)
+{
+
+       int exp_state, act_state;
+
+       get_detachstate(tnum, exp_attr, &exp_state);
+       get_detachstate(tnum, act_attr, &act_state);
+
+       if (exp_state != act_state) {
+               fprintf(logfp, "%d: Thread detach state mismatch: expected %d, "
+                               "actual %d\n", tnum, exp_state, act_state);
+               do_exit(1);
+       }
+}
+
+get_guardsize(int tnum, pthread_attr_t *attr, int *gsize)
+{
+       int rc;
+
+       rc = pthread_attr_getguardsize(attr, gsize);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_attr_getguardsize() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+}
+
+void compare_guardsize(int tnum, pthread_attr_t *exp_attr,
+               pthread_attr_t *act_attr)
+{
+       size_t exp_size, act_size;
+
+       get_guardsize(tnum, exp_attr, &exp_size);
+       get_guardsize(tnum, act_attr, &act_size);
+
+       if (exp_size != act_size) {
+               fprintf(logfp, "%d: Thread guard size mismatch, expected %d "
+                               "actual %d\n", tnum, exp_size, act_size);
+               do_exit(1);
+       }
+}
+
+get_inheritsched(int tnum, pthread_attr_t *attr, int *isched)
+{
+       int rc;
+
+       rc = pthread_attr_getinheritsched(attr, isched);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_attr_inheritsched() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+}
+
+void compare_inheritsched(int tnum, pthread_attr_t *exp_attr,
+               pthread_attr_t *act_attr)
+{
+       int exp_isched, act_isched;
+
+       get_inheritsched(tnum, exp_attr, &exp_isched);
+       get_inheritsched(tnum, act_attr, &act_isched);
+
+       if (exp_isched != act_isched) {
+               fprintf(logfp, "%d: Thread inherit-sched mismatch, expected %d "
+                               "actual %d\n", tnum, exp_isched, act_isched);
+               do_exit(1);
        }
+}
 
-       rc = pthread_attr_getstack(&attr, (void **)addrp, sizep);
+get_schedparam(int tnum, pthread_attr_t *attr, int *prio)
+{
+       int rc;
+       struct sched_param param;
+
+       rc = pthread_attr_getschedparam(attr, &param);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_attr_getschedparam() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+       *prio = param.__sched_priority;
+}
+
+compare_schedparam(int tnum, pthread_attr_t *exp_attr, pthread_attr_t 
*act_attr)
+{
+       int exp_prio, act_prio;
+
+       get_schedparam(tnum, exp_attr, &exp_prio);
+       get_schedparam(tnum, act_attr, &act_prio);
+
+       if (exp_prio != act_prio) {
+               fprintf(logfp, "%d: Thread sched-param mismatch, expected %d "
+                               "actual %d\n", tnum, exp_prio, act_prio);
+               do_exit(1);
+       }
+}
+
+get_schedpolicy(int tnum, pthread_attr_t *attr, int *policy)
+{
+       int rc;
+
+       rc = pthread_attr_getschedpolicy(attr, policy);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_attr_getschedpolicy() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+}
+
+compare_schedpolicy(int tnum, pthread_attr_t *exp_attr,
+                       pthread_attr_t *act_attr)
+{
+       int exp_policy, act_policy;
+
+       get_schedpolicy(tnum, exp_attr, &exp_policy);
+       get_schedpolicy(tnum, act_attr, &act_policy);
+
+       if (exp_policy != act_policy) {
+               fprintf(logfp, "%d: Thread sched-policy mismatch, expected %d "
+                               "actual %d\n", tnum, exp_policy, act_policy);
+               do_exit(1);
+       }
+}
+
+get_scope(int tnum, pthread_attr_t *attr, int *scope)
+{
+       int rc;
+
+       rc = pthread_attr_getscope(attr, scope);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_attr_getscope() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+}
+
+compare_scope(int tnum, pthread_attr_t *exp_attr, pthread_attr_t *act_attr)
+{
+       int exp_scope, act_scope;
+
+       get_scope(tnum, exp_attr, &exp_scope);
+       get_scope(tnum, act_attr, &act_scope);
+
+       if (exp_scope != act_scope) {
+               fprintf(logfp, "%d: Thread scope mismatch, expected %d "
+                               "actual %d\n", tnum, exp_scope, act_scope);
+               do_exit(1);
+       }
+}
+
+int get_stack(pthread_attr_t *attr, void **addrp, int *sizep)
+{
+       int rc;
+
+       rc = pthread_attr_getstack(attr, (void **)addrp, sizep);
        if (rc < 0) {
                fprintf(logfp, "pthread_attr_getstackaddr failed, rc %d, %s\n",
                                        rc, strerror(errno));
@@ -84,40 +256,145 @@ int get_stack_info(pthread_t tid, void **addrp, size_t 
*sizep)
        return 0;
 }
 
+void compare_stack(int tnum, pthread_attr_t *exp_attr,
+               pthread_attr_t *act_attr)
+{
+       int exp_size, act_size;
+       void *exp_addr, *act_addr;
+
+       get_stack(exp_attr, &exp_addr, &exp_size);
+       get_stack(act_attr, &act_addr, &act_size);
+
+       if (act_addr != exp_addr || act_size != exp_size) {
+               fprintf(logfp, "%d: Expected: (%p, %d), actual (%p, %d)\n",
+                               tnum, exp_addr, exp_size, act_addr, act_size);
+               fflush(logfp);
+               do_exit(1);
+       }
+}
+
+compare_attr(int tnum, pthread_attr_t *exp_attr, pthread_attr_t *act_attr)
+{
+
+       dump_attr("Expected attr", exp_attr);
+       dump_attr("Actual attr", act_attr);
+
+       /*
+        * We cannot simply memcmp() the exp_attr and act_attr since the
+        * 'struct pthread_attr' contains a pointer to cpuset. This address
+        * will be different even if the cpusets are the same
+        */
+       compare_affinity(tnum, exp_attr, act_attr);
+
+       compare_detachstate(tnum, exp_attr, act_attr);
+
+       compare_guardsize(tnum, exp_attr, act_attr);
+
+       compare_inheritsched(tnum, exp_attr, act_attr);
+
+       compare_schedparam(tnum, exp_attr, act_attr);
+
+       compare_schedpolicy(tnum, exp_attr, act_attr);
+
+       compare_scope(tnum, exp_attr, act_attr);
+
+       compare_stack(tnum, exp_attr, act_attr);
+}
+
 void *do_work(void *arg)
 {
        long tnum = (long)arg;
        int rc;
-       void *act_addr;
-       size_t act_size;
+       pthread_attr_t exp_attr, act_attr;
 
        fprintf(logfp, "%ld: Thread %lu: waiting for checkpoint\n", tnum,
                        pthread_self());
        fflush(logfp);
 
+       memset(&exp_attr, 0, sizeof(pthread_attr_t));
+       memset(&act_attr, 0, sizeof(pthread_attr_t));
+
+       /*
+        * Collect attributes before checkpoint/restart.
+        */
+       rc = pthread_getattr_np(pthread_self(), &exp_attr);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_getattr_np failed, rc %d, %s\n", rc,
+                               strerror(errno));
+               pthread_exit(ERROR_EXIT);
+       }
+
+       /*
+        * Inform main-thread we are ready for checkpoint.
+        */
+       rc = pthread_barrier_wait(&barrier);
+       if (rc != PTHREAD_BARRIER_SERIAL_THREAD && rc != 0) {
+               fprintf(logfp, "%d: pthread_barrier_wait() failed, rc %d, "
+                               "error %s\n", tnum, rc, strerror(errno));
+               do_exit(1);
+       }
+
+       /*
+        * Wait for checkpoint/restart.
+        */
        while(!test_done())
                sleep(1);
 
-       rc = get_stack_info(pthread_self(), &act_addr, &act_size);
-       if (rc < 0)
+       /*
+        * Collect attributes after checkpoint/restart.
+        */
+       rc = pthread_getattr_np(pthread_self(), &act_attr);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_getattr_np failed, rc %d, %s\n", rc,
+                               strerror(errno));
                pthread_exit(ERROR_EXIT);
-
-       if (act_addr != exp_addrs[tnum] || act_size != exp_sizes[tnum]) {
-               fprintf(logfp, "%d: Expected: (%p, %d), actual (%p, %d)\n",
-                               tnum, exp_addrs[tnum], exp_sizes[tnum],
-                               act_addr, act_size);
-               fflush(logfp);
-               rc = 1;
        }
 
-       fprintf(logfp, "%d: Thread %lu: exiting, rc %d\n", tnum,
-                       pthread_self(), rc);
+       /*
+        * Compare attributes before and after C/R.
+        */
+       compare_attr(tnum, &exp_attr, &act_attr);
+
+       fprintf(logfp, "%d: Thread %lu: exiting, rc 0\n", tnum,
+                       pthread_self());
        fflush(logfp);
 
-       tstatus[tnum] = rc;
+       tstatus[tnum] = 0;
        pthread_exit((void *)&tstatus[tnum]);
 }
 
+void set_stack(pthread_attr_t *attr, int tnum)
+{
+       int rc, size;
+       void *stack;
+
+       size = MIN_STACK_SIZE + (tnum * getpagesize());
+
+       stack = malloc(size);
+       if (!stack) {
+               fprintf(logfp, "malloc(stack): error %s\n", strerror(errno));
+               do_exit(1);
+       }
+
+       rc = pthread_attr_setstack(attr, stack, size);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_attr_setstack(): rc %d error %s\n",
+                               rc, strerror(errno));
+               do_exit(1);
+       }
+}
+
+/*
+ * Modify any attributes for this thread for testing.
+ * For now, we only modify the thread-stack.
+ */
+void set_thread_attrs(pthread_attr_t *attr, int tnum)
+{
+       set_stack(attr, tnum);
+
+       return;
+}
+
 pthread_t *create_threads(int n)
 {
        long i;
@@ -127,21 +404,21 @@ pthread_t *create_threads(int n)
        pthread_attr_t *attr;
 
        tid_list = (pthread_t *)malloc(n * sizeof(pthread_t));
-       exp_addrs = malloc(sizeof(void *) * n);
-       exp_sizes = malloc(sizeof(size_t) * n);
        tstatus = malloc(sizeof(int) * n);
 
-       if (!tid_list || !exp_addrs || !exp_sizes || !tstatus) {
+       if (!tid_list || !tstatus) {
                fprintf(logfp, "malloc() failed, n %d, error %s\n",
                                n, strerror(errno));
                do_exit(1);
        }
 
        for (i = 0; i < n; i++) {
-               attr = get_thread_attr(i);
+               attr = alloc_thread_attr();
                if (!attr)
                        do_exit(1);
 
+               set_thread_attrs(attr, i);
+
                rc = pthread_create(&tid, attr, do_work, (void *)i);
                if (rc < 0) {
                        fprintf(logfp, "pthread_create(): i %d, rc %d, "
@@ -149,10 +426,6 @@ pthread_t *create_threads(int n)
                        do_exit(1);
                }
 
-               rc = get_stack_info(tid, &exp_addrs[i], &exp_sizes[i]);
-               if (rc < 0)
-                       do_exit(1);
-
                tid_list[i] = tid;
        }
 
@@ -224,15 +497,46 @@ main(int argc, char *argv[])
                do_exit(1);
        }
 
+       fprintf(stderr, "Redirecting output to %s\n", log_file);
+       fflush(stderr);
+
        for (i=0; i<100; i++)  {
                if (fileno(logfp) != i)
                        close(i);
        }
 
 
+       /*
+        * Create a barrier which the main-thread can use to determine
+        * when all threads are ready for checkpoint.
+        */
+       rc = pthread_barrier_init(&barrier, NULL, num_threads+1);
+       if (rc < 0) {
+               fprintf(logfp, "pthread_barrier_init() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+
+       rc = pthread_mutex_init(&dump_lock, NULL);
+       if (rc) {
+               fprintf(logfp, "pthread_mutex_init() failed, rc %d, error %s\n",
+                               rc, strerror(errno));
+               do_exit(1);
+       }
+
        tid_list = create_threads(num_threads);
 
        /*
+        * Wait for everyone to be ready for checkpoint
+        */
+       pthread_barrier_wait(&barrier);
+       if (rc != PTHREAD_BARRIER_SERIAL_THREAD && rc != 0) {
+               fprintf(logfp, "main: pthread_barrier_wait() failed, rc %d, "
+                               "error %s\n", rc, strerror(errno));
+               do_exit(1);
+       }
+
+       /*
         * Now that we closed the special files and created the threads,
         * tell any wrapper scripts, we are ready for checkpoint
         */
@@ -240,5 +544,7 @@ main(int argc, char *argv[])
 
        rc = wait_for_threads(tid_list, num_threads);
 
+       fprintf(logfp, "Exiting with status %d\n", rc);
+
        do_exit(rc);
 }
diff --git a/process-tree/run-pthread2.sh b/process-tree/run-pthread2.sh
index 0686cbd..ff7f0ac 100755
--- a/process-tree/run-pthread2.sh
+++ b/process-tree/run-pthread2.sh
@@ -2,8 +2,7 @@
 
 source ../common.sh
 
-#dir=`mktemp -p . -d -t cr_pthread2_XXXXXXX` || (echo "mktemp failed"; exit 1)
-dir=cr_pthread2
+dir=`mktemp -p . -d -t cr_pthread2_XXXXXXX` || (echo "mktemp failed"; exit 1)
 mkdir $dir
 echo "Using output dir $dir"
 cd $dir
@@ -17,7 +16,7 @@ RESTART=`which restart`
 ECHO="/bin/echo -e"
 
 TEST_CMD="../pthread2"
-TEST_ARGS="-n 128"                     # -n: number of threads
+TEST_ARGS="-n 4"                       # -n: number of threads
 SCRIPT_LOG="log-run-pthread2"
 TEST_PID_FILE="pid.pthread2";
 
-- 
1.6.0.4

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to