File: lock.c

package info (click to toggle)
criu 4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,500 kB
  • sloc: ansic: 139,280; python: 7,484; sh: 3,824; java: 2,799; makefile: 2,659; asm: 1,137; perl: 206; xml: 117; exp: 45
file content (87 lines) | stat: -rw-r--r-- 1,811 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#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());
}