[CRIU] Re: [PATCH 1/2] zdtm: Add task_waiter_ helpers v3
Andrew Vagin
avagin at parallels.com
Fri Jun 22 05:59:26 EDT 2012
Acked
I don't know why do you need sys_gettid(). Why get sid from glibc is not
suitable.
On Tue, Jun 19, 2012 at 07:05:30PM +0400, Cyrill Gorcunov wrote:
> Sometime we need sync points in testee program flow,
> for this reason task_waiter_ introduced.
>
> The call semantics is the following
>
> Parent Child
> ------ -----
> task_waiter_init
> task_waiter_wait4
> task_waiter_complete
> task_waiter_wait4
> task_waiter_complete
>
> ...
>
> Thus initially task_waiter_init should be called
> to initialize all internals guts needed.
>
> Then one become waitee and calls for task_waiter_wait4,
> where lockid should be provided as an argument. Since
> it should be unique values the best option might be
> gettid().
>
> The same applies to a waiter side -- it should call
> for task_waiter_complete and provide a lockid.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> test/zdtm/lib/Makefile | 2 +-
> test/zdtm/lib/lock.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++
> test/zdtm/lib/zdtmtst.h | 11 +++++
> 3 files changed, 106 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..7f8f522
> --- /dev/null
> +++ b/test/zdtm/lib/lock.c
> @@ -0,0 +1,94 @@
> +#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
> +
> +static long sys_gettid(void)
> +{
> + long ret;
> +
> + asm volatile("movl $186, %%eax \n"
> + "syscall \n"
> + "movq %%rax, %0 \n"
> + : "=r"(ret)
> + :
> + : "rax", "memory");
> + return ret;
> +}
Why can you not use gettid() from glibc?
> +
> +void task_waiter_init(task_waiter_t *t)
> +{
> + datagen((void *)&t->seed, sizeof(t->seed), NULL);
> + t->seed = t->seed % TASK_WAITER_INITIAL;
What about t->seed = 0;
> +
> + 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_wait4(task_waiter_t *t, unsigned int lockid)
> +{
> + struct timespec req = { .tv_nsec = TASK_WAITER_INITIAL, };
> + struct timespec rem = { };
> + unsigned int v;
> +
> + for (;;) {
> + if (read(t->pipes[0], &v, sizeof(v)) != sizeof(v))
> + goto err;
> +
> + /*
> + * If we read a value not intended for us, say parent
> + * waits for specified child to complete among set of
> + * children, or we just have completed and wait for
> + * another lockid from a parent -- we need to write
> + * the value back and wait for some time before
> + * next attempt.
> + */
> + if (v != lockid) {
> + if (write(t->pipes[1], &v, sizeof(v)) != sizeof(v))
> + goto err;
> + /*
> + * If we get a collision in access, lets sleep
> + * semi-random time magnitude to decrease probability
> + * of a new collision.
> + */
> + nanosleep(&req, &rem);
> + req.tv_nsec += t->seed;
> + } else
> + break;
> + }
> +
> + return;
> +
> +err:
> + err("task_waiter_wait4 failed: %m");
> + exit(errno);
> +}
> +
> +void task_waiter_complete(task_waiter_t *t, unsigned int lockid)
> +{
> + if (write(t->pipes[1], &lockid, sizeof(lockid)) != sizeof(lockid)) {
> + err("task_waiter_complete failed: %m");
> + exit(1);
> + }
> +}
> +
> +void task_waiter_complete_current(task_waiter_t *t)
> +{
> + return task_waiter_complete(t, (int)sys_gettid());
> +}
> diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h
> index 6ef7804..1f12d41 100644
> --- a/test/zdtm/lib/zdtmtst.h
> +++ b/test/zdtm/lib/zdtmtst.h
> @@ -89,4 +89,15 @@ extern int parse_opt_string(char *param, void *arg);
> __FILE__, __LINE__, ## arg)
> #define pass() test_msg("PASS\n")
>
> +typedef struct {
> + 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_wait4(task_waiter_t *t, unsigned int lockid);
> +extern void task_waiter_complete(task_waiter_t *t, unsigned int lockid);
> +extern void task_waiter_complete_current(task_waiter_t *t);
> +
> #endif /* _VIMITESU_H_ */
> --
> 1.7.7.6
>
More information about the CRIU
mailing list