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