[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