Commit aabeb8e4 authored by Andrei Vagin's avatar Andrei Vagin Committed by Pavel Emelyanov

zdtm: use a unix socket instead of a pipe to synchronizer processes

A unix socket can be bound to itself, so we need only one socket
instead of a pair of pipe.

If we use a socket, we can peek a message and if it isn't for us
we don't need to send it back.

Currently a process reads message from pipe, if it isn't for him,
it sends it back and sleeps for a random timeout. In a worst case
each waiter will read and send a message back, before the right
one will get it.

travis-ci: success for series starting with [1/3] zdtm: call test_init() before doing anything
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent f5df0ada
......@@ -7,6 +7,9 @@
#include <unistd.h>
#include <linux/unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include "zdtmtst.h"
......@@ -19,19 +22,52 @@ static long sys_gettid(void)
void task_waiter_init(task_waiter_t *t)
{
struct sockaddr_un addr;
unsigned int addrlen;
struct stat st;
int sk;
datagen((void *)&t->seed, sizeof(t->seed), NULL);
t->seed = t->seed % TASK_WAITER_INITIAL;
if (pipe(t->pipes)) {
pr_perror("task_waiter_init failed");
exit(1);
sk = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sk < 0) {
pr_perror("Unable to create a socket");
goto err;
}
if (fstat(sk, &st)) {
pr_perror("Unable to stat a file descriptor");
close(sk);
goto err;
}
addr.sun_family = AF_UNIX;
addrlen = snprintf(addr.sun_path, sizeof(addr.sun_path), "X/criu-zdtm-%lx", st.st_ino);
addrlen += sizeof(addr.sun_family);
addr.sun_path[0] = 0;
if (bind(sk, &addr, addrlen)) {
pr_perror("Unable to bind a socket");
close(sk);
goto err;
}
if (connect(sk, &addr, addrlen)) {
pr_perror("Unable to connect a socket");
close(sk);
goto err;
}
t->sk = sk;
return;
err:
exit(1);
}
void task_waiter_fini(task_waiter_t *t)
{
close(t->pipes[0]);
close(t->pipes[1]);
close(t->sk);
t->sk = -1;
}
void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
......@@ -41,7 +77,7 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
unsigned int v;
for (;;) {
if (read(t->pipes[0], &v, sizeof(v)) != sizeof(v))
if (recv(t->sk, &v, sizeof(v), MSG_PEEK) != sizeof(v))
goto err;
/*
......@@ -53,8 +89,6 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
* 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
......@@ -65,6 +99,8 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
} else
break;
}
if (recv(t->sk, &v, sizeof(v), 0) != sizeof(v))
goto err;
return;
......@@ -75,7 +111,7 @@ err:
void task_waiter_complete(task_waiter_t *t, unsigned int lockid)
{
if (write(t->pipes[1], &lockid, sizeof(lockid)) != sizeof(lockid)) {
if (write(t->sk, &lockid, sizeof(lockid)) != sizeof(lockid)) {
pr_perror("task_waiter_complete failed");
exit(1);
}
......
......@@ -129,7 +129,7 @@ extern int zdtm_seccomp;
typedef struct {
unsigned long seed;
int pipes[2];
int sk;
} task_waiter_t;
extern void task_waiter_init(task_waiter_t *t);
......
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