4-1.c revision e79aabe2ffaa0e804c80121922e6f6de7651d4de
1/*
2 * Copyright (c) 2004, Bull SA. All rights reserved.
3 * Created by:  Laurent.Vivier@bull.net
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7 */
8
9/*
10 * assertion:
11 *
12 *	On a timeout exit, aio_suspend shall return with an error.
13 *
14 * method: Testing for a non NULL timeout
15 *
16 *	- write to a file
17 *	- submit a list of read requests
18 *	- check that the selected request has not completed
19 *	- suspend on selected request
20 *	- check that the suspend timed out
21 *	- check return code and errno
22 *
23 */
24
25#define _XOPEN_SOURCE 600
26#include <sys/stat.h>
27#include <aio.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <signal.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
35
36#include "posixtest.h"
37
38#define TNAME "aio_suspend/4-1.c"
39
40#define NUM_AIOCBS	10
41#define BUF_SIZE	1024*1024
42#define WAIT_FOR_AIOCB	6
43
44int received_selected	= 0;
45int received_all	= 0;
46
47void
48sigrt1_handler(int signum, siginfo_t *info, void *context)
49{
50	received_selected = 1;
51}
52
53void
54sigrt2_handler(int signum, siginfo_t *info, void *context)
55{
56	received_all = 1;
57}
58
59int
60main ()
61{
62	char tmpfname[256];
63	int fd;
64
65	struct aiocb **aiocbs;
66	struct aiocb *plist[2];
67	char *bufs;
68	struct sigaction action;
69	struct sigevent event;
70	struct timespec ts = {0, 1000}; /* 1 us */
71	int errors = 0;
72	int ret;
73	int err;
74	int i;
75
76	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
77		return PTS_UNSUPPORTED;
78
79	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_suspend_4_1_%d",
80		  getpid());
81	unlink(tmpfname);
82
83	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
84
85	if (fd == -1) {
86		printf(TNAME " Error at open(): %s\n",
87		       strerror(errno));
88		exit(PTS_UNRESOLVED);
89	}
90
91	unlink(tmpfname);
92
93	bufs = (char *) malloc (NUM_AIOCBS*BUF_SIZE);
94
95	if (bufs == NULL) {
96		printf (TNAME " Error at malloc(): %s\n", strerror (errno));
97		close (fd);
98		exit(PTS_UNRESOLVED);
99	}
100
101	if (write (fd, bufs, NUM_AIOCBS*BUF_SIZE) != (NUM_AIOCBS*BUF_SIZE)) {
102		printf(TNAME " Error at write(): %s\n", strerror(errno));
103		free (bufs);
104		close (fd);
105		exit(PTS_UNRESOLVED);
106	}
107
108	aiocbs = (struct aiocb**)malloc(sizeof(struct aiocb *) * NUM_AIOCBS);
109
110	/* Queue up a bunch of aio reads */
111	for (i = 0; i < NUM_AIOCBS; i++) {
112
113		aiocbs[i] = (struct aiocb*)malloc(sizeof(struct aiocb));
114		memset(aiocbs[i], 0, sizeof(struct aiocb));
115
116		aiocbs[i]->aio_fildes = fd;
117		aiocbs[i]->aio_offset = i * BUF_SIZE;
118		aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE];
119		aiocbs[i]->aio_nbytes = BUF_SIZE;
120		aiocbs[i]->aio_lio_opcode = LIO_READ;
121
122		/* Use SIGRTMIN+1 for individual completions */
123		if (i == WAIT_FOR_AIOCB) {
124			aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
125			aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN+1;
126			aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
127		}
128	}
129
130	/* Use SIGRTMIN+2 for list completion */
131	event.sigev_notify = SIGEV_SIGNAL;
132	event.sigev_signo = SIGRTMIN+2;
133	event.sigev_value.sival_ptr = NULL;
134
135	/* Setup handler for individual operation completion */
136	action.sa_sigaction = sigrt1_handler;
137	sigemptyset(&action.sa_mask);
138	action.sa_flags = SA_SIGINFO|SA_RESTART;
139	sigaction(SIGRTMIN+1, &action, NULL);
140
141	/* Setup handler for list completion */
142	action.sa_sigaction = sigrt2_handler;
143	sigemptyset(&action.sa_mask);
144	action.sa_flags = SA_SIGINFO|SA_RESTART;
145	sigaction(SIGRTMIN+2, &action, NULL);
146
147	/* Setup suspend list */
148	plist[0] = NULL;
149	plist[1] = aiocbs[WAIT_FOR_AIOCB];
150
151	/* Submit request list */
152	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);
153
154	if (ret) {
155		printf(TNAME " Error at lio_listio() %d: %s\n", errno, strerror(errno));
156		for (i=0; i<NUM_AIOCBS; i++)
157			free (aiocbs[i]);
158		free (bufs);
159		free (aiocbs);
160		close (fd);
161		exit (PTS_UNRESOLVED);
162	}
163
164	/* Check selected request has not completed yet */
165	if (received_selected) {
166		printf (TNAME " Error : AIOCB %d already completed before suspend\n",
167			WAIT_FOR_AIOCB);
168		for (i=0; i<NUM_AIOCBS; i++)
169			free (aiocbs[i]);
170		free (bufs);
171		free (aiocbs);
172		close (fd);
173		exit (PTS_FAIL);
174	}
175
176	/* Suspend on selected request */
177	ret = aio_suspend((const struct aiocb **)plist, 2, &ts);
178
179	/* Check selected request has not completed */
180	if (received_selected) {
181		printf (TNAME " Error : AIOCB %d should not have completed after timed out suspend\n",
182			WAIT_FOR_AIOCB);
183		for (i=0; i<NUM_AIOCBS; i++)
184			free (aiocbs[i]);
185		free (bufs);
186		free (aiocbs);
187		close (fd);
188		exit (PTS_FAIL);
189	}
190
191	/* timed out aio_suspend should return -1 and set errno to EAGAIN */
192	if (ret != -1) {
193		printf (TNAME " aio_suspend() should return -1\n");
194		for (i=0; i<NUM_AIOCBS; i++)
195			free (aiocbs[i]);
196		free (bufs);
197		free (aiocbs);
198		close (fd);
199		exit (PTS_FAIL);
200	}
201
202	if (errno != EAGAIN) {
203		printf (TNAME " aio_suspend() should set errno to EAGAIN: %d (%s)\n",
204			errno, strerror (errno));
205		for (i=0; i<NUM_AIOCBS; i++)
206			free (aiocbs[i]);
207		free (bufs);
208		free (aiocbs);
209		close (fd);
210		exit (PTS_FAIL);
211	}
212
213	/* Wait for list processing completion */
214	while (!received_all)
215		sleep (1);
216
217	/* Check return code and free things */
218	for (i = 0; i < NUM_AIOCBS; i++) {
219	  	err = aio_error(aiocbs[i]);
220		ret = aio_return(aiocbs[i]);
221
222		if ((err != 0) && (ret != BUF_SIZE)) {
223			printf(TNAME " req %d: error = %d - return = %d\n", i, err, ret);
224			errors++;
225		}
226
227		free (aiocbs[i]);
228	}
229
230	free (bufs);
231	free (aiocbs);
232
233	close(fd);
234
235	if (errors != 0)
236		exit (PTS_FAIL);
237
238	printf (TNAME " PASSED\n");
239
240	return PTS_PASS;
241}
242