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