[CRIU] [PATCH 3/3] zdtm: use a unix socket instead of a pipe to synchronizer processes
Andrei Vagin
avagin at openvz.org
Thu Dec 29 17:28:38 PST 2016
From: Andrei Vagin <avagin at virtuozzo.com>
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.
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
test/zdtm/lib/lock.c | 54 ++++++++++++++++++++++++++++++++++++++++---------
test/zdtm/lib/zdtmtst.h | 2 +-
2 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/test/zdtm/lib/lock.c b/test/zdtm/lib/lock.c
index 9d2a646..9c3ec87 100644
--- a/test/zdtm/lib/lock.c
+++ b/test/zdtm/lib/lock.c
@@ -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);
}
diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h
index 3f9f550..9770f74 100644
--- a/test/zdtm/lib/zdtmtst.h
+++ b/test/zdtm/lib/zdtmtst.h
@@ -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);
--
2.7.4
More information about the CRIU
mailing list