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 @@ ...@@ -7,6 +7,9 @@
#include <unistd.h> #include <unistd.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <time.h> #include <time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include "zdtmtst.h" #include "zdtmtst.h"
...@@ -19,19 +22,52 @@ static long sys_gettid(void) ...@@ -19,19 +22,52 @@ static long sys_gettid(void)
void task_waiter_init(task_waiter_t *t) 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); datagen((void *)&t->seed, sizeof(t->seed), NULL);
t->seed = t->seed % TASK_WAITER_INITIAL; t->seed = t->seed % TASK_WAITER_INITIAL;
if (pipe(t->pipes)) { sk = socket(AF_UNIX, SOCK_DGRAM, 0);
pr_perror("task_waiter_init failed"); if (sk < 0) {
exit(1); 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) void task_waiter_fini(task_waiter_t *t)
{ {
close(t->pipes[0]); close(t->sk);
close(t->pipes[1]); t->sk = -1;
} }
void task_waiter_wait4(task_waiter_t *t, unsigned int lockid) 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) ...@@ -41,7 +77,7 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
unsigned int v; unsigned int v;
for (;;) { for (;;) {
if (read(t->pipes[0], &v, sizeof(v)) != sizeof(v)) if (recv(t->sk, &v, sizeof(v), MSG_PEEK) != sizeof(v))
goto err; goto err;
/* /*
...@@ -53,8 +89,6 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid) ...@@ -53,8 +89,6 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
* next attempt. * next attempt.
*/ */
if (v != lockid) { if (v != lockid) {
if (write(t->pipes[1], &v, sizeof(v)) != sizeof(v))
goto err;
/* /*
* If we get a collision in access, lets sleep * If we get a collision in access, lets sleep
* semi-random time magnitude to decrease probability * semi-random time magnitude to decrease probability
...@@ -65,6 +99,8 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid) ...@@ -65,6 +99,8 @@ void task_waiter_wait4(task_waiter_t *t, unsigned int lockid)
} else } else
break; break;
} }
if (recv(t->sk, &v, sizeof(v), 0) != sizeof(v))
goto err;
return; return;
...@@ -75,7 +111,7 @@ err: ...@@ -75,7 +111,7 @@ err:
void task_waiter_complete(task_waiter_t *t, unsigned int lockid) 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"); pr_perror("task_waiter_complete failed");
exit(1); exit(1);
} }
......
...@@ -129,7 +129,7 @@ extern int zdtm_seccomp; ...@@ -129,7 +129,7 @@ extern int zdtm_seccomp;
typedef struct { typedef struct {
unsigned long seed; unsigned long seed;
int pipes[2]; int sk;
} task_waiter_t; } task_waiter_t;
extern void task_waiter_init(task_waiter_t *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