[CRIU] [PATCH 18/21] zdtm: Add task_waiter_ helpers v2

Cyrill Gorcunov gorcunov at openvz.org
Wed Jun 6 18:21:58 EDT 2012


Sometime we need sync points in testee program
flow, for this reason task_waiter_ introduced.

The call semantics is the following

a) The fork() is used so both parent and child do not
   share memory referenced by task waiter. Thus the calling
   sequence should be

        Parent                  Child
        ------                  -----
        task_waiter_init
                                task_waiter_wait
        task_waiter_complete
        task_waiter_update
                                task_waiter_wait
        task_waiter_complete
        task_waiter_update

                ...

b) If shared memory is used then no need to call
   for task_waiter_update.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 test/zdtm/lib/Makefile  |    2 +-
 test/zdtm/lib/lock.c    |   81 +++++++++++++++++++++++++++++++++++++++++++++++
 test/zdtm/lib/zdtmtst.h |   12 +++++++
 3 files changed, 94 insertions(+), 1 deletions(-)
 create mode 100644 test/zdtm/lib/lock.c

diff --git a/test/zdtm/lib/Makefile b/test/zdtm/lib/Makefile
index a4ab681..f09e71f 100644
--- a/test/zdtm/lib/Makefile
+++ b/test/zdtm/lib/Makefile
@@ -2,7 +2,7 @@ CFLAGS	= -g -O2 -Wall -Werror -Wno-unused-result
 
 LIB	= libzdtmtst.a
 
-LIBSRC	= datagen.c msg.c parseargs.c test.c streamutil.c
+LIBSRC	= datagen.c msg.c parseargs.c test.c streamutil.c lock.c
 LIBOBJ	= $(LIBSRC:%.c=%.o)
 LIBDEP	= $(LIBSRC:%.c=%.d)
 
diff --git a/test/zdtm/lib/lock.c b/test/zdtm/lib/lock.c
new file mode 100644
index 0000000..1959fc8
--- /dev/null
+++ b/test/zdtm/lib/lock.c
@@ -0,0 +1,81 @@
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "zdtmtst.h"
+
+#define TASK_WAITER_INITIAL		0x0fffff
+
+void task_waiter_init(task_waiter_t *t)
+{
+	t->raw = 1;
+	datagen((void *)&t->seed, sizeof(t->seed), NULL);
+
+	t->seed = t->seed % TASK_WAITER_INITIAL;
+
+	if (pipe(t->pipes)) {
+		err("task_waiter_init failed: %m");
+		exit(1);
+	}
+}
+
+void task_waiter_fini(task_waiter_t *t)
+{
+	close(t->pipes[0]);
+	close(t->pipes[1]);
+}
+
+void task_waiter_wait(task_waiter_t *t)
+{
+	struct timespec req = { .tv_nsec = TASK_WAITER_INITIAL, };
+	struct timespec rem = { };
+	int v, attempts = 5;
+
+	for (;;) {
+		if (!attempts--) {
+			errno = EAGAIN;
+			goto err;
+		}
+		if (read(t->pipes[0], &v, sizeof(v)) !=  sizeof(v))
+			goto err;
+		if (v != t->raw + 1) {
+			if (write(t->pipes[1], &v, sizeof(v)) !=  sizeof(v))
+				goto err;
+			nanosleep(&req, &rem);
+			req.tv_nsec += t->seed;
+		} else {
+			t->raw++;
+			break;
+		}
+	}
+
+	return;
+
+err:
+	err("task_waiter_wait failed: %m");
+	exit(errno);
+}
+
+void task_waiter_complete(task_waiter_t *t)
+{
+	int v = t->raw + 1;
+	if (write(t->pipes[1], &v, sizeof(v)) !=  sizeof(v)) {
+		err("task_waiter_complete failed: %m");
+		exit(1);
+	}
+}
+
+/*
+ * If waiter and watee do not share memory to task_waiter_t (ie
+ * the fork() was used), then once task_waiter_complete called
+ * the task_waiter_update should be invoked as well.
+ */
+void task_waiter_update(task_waiter_t *t)
+{
+	t->raw++;
+}
diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h
index 6ef7804..2a77a21 100644
--- a/test/zdtm/lib/zdtmtst.h
+++ b/test/zdtm/lib/zdtmtst.h
@@ -89,4 +89,16 @@ extern int parse_opt_string(char *param, void *arg);
 		 __FILE__, __LINE__, ## arg)
 #define pass()	test_msg("PASS\n")
 
+typedef struct {
+	unsigned int	raw;
+	unsigned long	seed;
+	int		pipes[2];
+} task_waiter_t;
+
+extern void task_waiter_init(task_waiter_t *t);
+extern void task_waiter_fini(task_waiter_t *t);
+extern void task_waiter_wait(task_waiter_t *t);
+extern void task_waiter_complete(task_waiter_t *t);
+extern void task_waiter_update(task_waiter_t *t);
+
 #endif /* _VIMITESU_H_ */
-- 
1.7.7.6



More information about the CRIU mailing list