4-1.c revision ec5557833ef9b56de0a174b976d06dce396b4112
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	if (info->si_value.sival_int == WAIT_FOR_AIOCB)
51		received_selected = 1;
52}
53
54void
55sigrt2_handler(int signum, siginfo_t *info, void *context)
56{
57	received_all = 1;
58}
59
60int
61main ()
62{
63	char tmpfname[256];
64	int fd;
65
66	struct aiocb **aiocbs;
67	struct aiocb *plist[2];
68	char *bufs;
69	struct sigaction action;
70	struct sigevent event;
71	struct timespec ts = {0, 10000000}; /* 10 ms */
72	int errors = 0;
73	int ret;
74	int err;
75	int i;
76
77	if (sysconf(_SC_ASYNCHRONOUS_IO) != 200112L)
78		return PTS_UNSUPPORTED;
79
80	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_suspend_4_1_%d",
81		  getpid());
82	unlink(tmpfname);
83
84	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
85
86	if (fd == -1) {
87		printf(TNAME " Error at open(): %s\n",
88		       strerror(errno));
89		exit(PTS_UNRESOLVED);
90	}
91
92	unlink(tmpfname);
93
94	bufs = (char *) malloc (NUM_AIOCBS*BUF_SIZE);
95
96	if (bufs == NULL) {
97		printf (TNAME " Error at malloc(): %s\n", strerror (errno));
98		close (fd);
99		exit(PTS_UNRESOLVED);
100	}
101
102	if (write (fd, bufs, NUM_AIOCBS*BUF_SIZE) != (NUM_AIOCBS*BUF_SIZE)) {
103		printf(TNAME " Error at write(): %s\n", strerror(errno));
104		free (bufs);
105		close (fd);
106		exit(PTS_UNRESOLVED);
107	}
108
109
110
111	aiocbs = (struct aiocb**)malloc(sizeof(struct aiocb *) * NUM_AIOCBS);
112
113	/* Queue up a bunch of aio reads */
114	for (i = 0; i < NUM_AIOCBS; i++) {
115
116		aiocbs[i] = (struct aiocb*)malloc(sizeof(struct aiocb));
117		memset(aiocbs[i], 0, sizeof(struct aiocb));
118
119		aiocbs[i]->aio_fildes = fd;
120		aiocbs[i]->aio_offset = i * BUF_SIZE;
121		aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE];
122		aiocbs[i]->aio_nbytes = BUF_SIZE;
123		aiocbs[i]->aio_lio_opcode = LIO_READ;
124
125		/* Use SIRTMIN+1 for individual completions */
126		aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
127		aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN+1;
128		aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
129	}
130
131	/* Use SIGRTMIN+2 for list completion */
132	event.sigev_notify = SIGEV_SIGNAL;
133	event.sigev_signo = SIGRTMIN+2;
134	event.sigev_value.sival_ptr = NULL;
135
136	/* Setup handler for individual operation completion */
137	action.sa_sigaction = sigrt1_handler;
138	sigemptyset(&action.sa_mask);
139	action.sa_flags = SA_SIGINFO|SA_RESTART;
140	sigaction(SIGRTMIN+1, &action, NULL);
141
142	/* Setup handler for list completion */
143	action.sa_sigaction = sigrt2_handler;
144	sigemptyset(&action.sa_mask);
145	action.sa_flags = SA_SIGINFO|SA_RESTART;
146	sigaction(SIGRTMIN+2, &action, NULL);
147
148	/* Setup suspend list */
149	plist[0] = NULL;
150	plist[1] = aiocbs[WAIT_FOR_AIOCB];
151
152	/* Submit request list */
153	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);
154
155	if (ret) {
156		printf(TNAME " Error at lio_listio() %d: %s\n", errno, strerror(errno));
157		for (i=0; i<NUM_AIOCBS; i++)
158			free (aiocbs[i]);
159		free (bufs);
160		free (aiocbs);
161		close (fd);
162		exit (PTS_UNRESOLVED);
163	}
164
165	/* Check selected request has not completed yet */
166	if (received_selected) {
167		printf (TNAME " Error : AIOCB %d already completed before suspend\n",
168			WAIT_FOR_AIOCB);
169		for (i=0; i<NUM_AIOCBS; i++)
170			free (aiocbs[i]);
171		free (bufs);
172		free (aiocbs);
173		close (fd);
174		exit (PTS_FAIL);
175	}
176
177	/* Suspend on selected request */
178	ret = aio_suspend((const struct aiocb **)plist, 2, &ts);
179
180	/* Check selected request has not completed */
181	if (received_selected) {
182		printf (TNAME " Error : AIOCB %d should not have completed after timed out suspend\n",
183			WAIT_FOR_AIOCB);
184		for (i=0; i<NUM_AIOCBS; i++)
185			free (aiocbs[i]);
186		free (bufs);
187		free (aiocbs);
188		close (fd);
189		exit (PTS_FAIL);
190	}
191
192	/* timed out aio_suspend should return -1 and set errno to EAGAIN */
193	if (ret != -1) {
194		printf (TNAME " aio_suspend() should return -1\n");
195		for (i=0; i<NUM_AIOCBS; i++)
196			free (aiocbs[i]);
197		free (bufs);
198		free (aiocbs);
199		close (fd);
200		exit (PTS_FAIL);
201	}
202
203	if (errno != EAGAIN) {
204		printf (TNAME " aio_suspend() should set errno to EAGAIN: %d (%s)\n",
205			errno, strerror (errno));
206		for (i=0; i<NUM_AIOCBS; i++)
207			free (aiocbs[i]);
208		free (bufs);
209		free (aiocbs);
210		close (fd);
211		exit (PTS_FAIL);
212	}
213
214	/* Wait for list processing completion */
215	while (!received_all)
216		sleep (1);
217
218	/* Check return code and free things */
219	for (i = 0; i < NUM_AIOCBS; i++) {
220	  	err = aio_error(aiocbs[i]);
221		ret = aio_return(aiocbs[i]);
222
223		if ((err != 0) && (ret != BUF_SIZE)) {
224			printf(TNAME " req %d: error = %d - return = %d\n", i, err, ret);
225			errors++;
226		}
227
228		free (aiocbs[i]);
229	}
230
231	free (bufs);
232	free (aiocbs);
233
234	close(fd);
235
236	if (errors != 0)
237		exit (PTS_FAIL);
238
239	printf (TNAME " PASSED\n");
240
241	return PTS_PASS;
242}
243