Commit 8d7a55ed authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

zdtm: Add task_waiter_ helpers v3

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: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Acked-by: 's avatarAndrey Vagin <avagin@parallels.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 43f62f42
...@@ -2,7 +2,7 @@ CFLAGS = -g -O2 -Wall -Werror -Wno-unused-result ...@@ -2,7 +2,7 @@ CFLAGS = -g -O2 -Wall -Werror -Wno-unused-result
LIB = libzdtmtst.a 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) LIBOBJ = $(LIBSRC:%.c=%.o)
LIBDEP = $(LIBSRC:%.c=%.d) LIBDEP = $(LIBSRC:%.c=%.d)
......
#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;
}
void task_waiter_init(task_waiter_t *t)
{
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_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());
}
...@@ -89,4 +89,15 @@ extern int parse_opt_string(char *param, void *arg); ...@@ -89,4 +89,15 @@ extern int parse_opt_string(char *param, void *arg);
__FILE__, __LINE__, ## arg) __FILE__, __LINE__, ## arg)
#define pass() test_msg("PASS\n") #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_ */ #endif /* _VIMITESU_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment