summaryrefslogtreecommitdiff
path: root/tests/aio/aio-multithread-test.c
blob: 1a41b2cf56eded790a668ff6d8a767a3253c43ae (plain)
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#define _GNU_SOURCE
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS	64

#include <errno.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <libaio.h>
#include <pthread.h>

uint64_t nr_blocks = 1024 * 1024 * 4;
int fd;
io_context_t ioctx;

uint64_t getblocks(int fd)
{
	uint64_t ret;
	struct stat statbuf;
	if (fstat(fd, &statbuf)) {
		perror("stat error\n");
		exit(EXIT_FAILURE);
	}
	ret = statbuf.st_size / 512;
	if (S_ISBLK(statbuf.st_mode))
		if (ioctl(fd, BLKGETSIZE, &ret)) {
			perror("ioctl error");
			exit(EXIT_FAILURE);
		}
	return ret / 8;
}

static void *iothread(void *p)
{
	char __attribute__((aligned(4096))) buf[4096];
	unsigned seed = 0;

	while (1) {
		struct iocb iocb[64];
		struct iocb *iocbp[64];
		unsigned i;
		int ret;

		memset(iocb, 0, sizeof(struct iocb) * 64);

		for (i = 0; i < 64; i++) {
			uint64_t offset = rand_r(&seed);

			iocb[i].aio_lio_opcode = IO_CMD_PREAD;
			iocb[i].aio_fildes = fd;

			iocb[i].u.c.buf = buf;
			iocb[i].u.c.nbytes = 4096;
			iocb[i].u.c.offset = (offset % nr_blocks) * 4096;

			iocbp[i] = &iocb[i];
		}

		ret = io_submit(ioctx, 64, iocbp);
		if (ret < 0 && ret != -EAGAIN)
			printf("io_submit() error %i\n", ret);

	}

	return NULL;
}

int main(int argc, char **argv)
{
	pthread_t threads[4];
	unsigned i;

	memset(threads, 0, sizeof(pthread_t) * 4);

#if 0
	if (argc != 2) {
		printf("Specify a file/device to test against\n");
		exit(EXIT_FAILURE);
	}

	fd = open(argv[1], O_RDONLY|O_DIRECT);
#else
	fd = open("/dev/zero", O_RDONLY);
#endif
	if (fd < 0) {
		perror("Open error");
		exit(EXIT_FAILURE);
	}

	//nr_blocks = getblocks(fd);

	if (io_setup(128, &ioctx)) {
		perror("Error creating io context");
		exit(EXIT_FAILURE);
	}

	for (i = 0; i < 8; i++)
		if (pthread_create(&threads[i], NULL, iothread, NULL)) {
			printf("pthread_create() error\n");
			exit(EXIT_FAILURE);
		}

	for (i = 0; i < 1000 * 1000;) {
		struct timespec timeout;
		struct io_event events[256];
		int ret;

		timeout.tv_sec = 0;
		timeout.tv_nsec = 10000;

		ret = io_getevents(ioctx, 1, 256, events, &timeout);
		if (ret < 0)
			printf("io_getevents error\n");
		else
			i += ret;

	}

	printf("exiting\n");
	io_destroy(ioctx);
	printf("io_destroy done\n");

	exit(EXIT_SUCCESS);
}