mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-19 09:35:12 +00:00
There is an another err() in glibc Signed-off-by: Andrew Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
87 lines
1.8 KiB
C
87 lines
1.8 KiB
C
#define _GNU_SOURCE
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <linux/unistd.h>
|
|
#include <time.h>
|
|
|
|
#include "zdtmtst.h"
|
|
|
|
#define TASK_WAITER_INITIAL 0x0fffff
|
|
|
|
static long sys_gettid(void)
|
|
{
|
|
return syscall(__NR_gettid);
|
|
}
|
|
|
|
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)) {
|
|
pr_perror("task_waiter_init failed");
|
|
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:
|
|
pr_perror("task_waiter_wait4 failed");
|
|
exit(errno);
|
|
}
|
|
|
|
void task_waiter_complete(task_waiter_t *t, unsigned int lockid)
|
|
{
|
|
if (write(t->pipes[1], &lockid, sizeof(lockid)) != sizeof(lockid)) {
|
|
pr_perror("task_waiter_complete failed");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void task_waiter_complete_current(task_waiter_t *t)
|
|
{
|
|
return task_waiter_complete(t, (int)sys_gettid());
|
|
}
|