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