[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